Skip to content

Commit

Permalink
feat: more detailed warning for non esm dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed May 19, 2020
1 parent a0fb9fb commit 0e68cc1
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 19 deletions.
58 changes: 45 additions & 13 deletions src/node/depOptimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export interface DepOptimizationOptions {
* Do not optimize these dependencies.
*/
exclude?: string[]
/**
* Explicitly allow these CommonJS deps to be bundled.
*/
commonJSWhitelist?: string[]
/**
* Automatically run `vite optimize` on server start?
* @default true
Expand Down Expand Up @@ -84,17 +88,16 @@ export async function optimizeDeps(
}

const resolver = createResolver(root, config.resolvers, config.alias)
const { include, exclude } = config.optimizeDeps || {}
const { include, exclude, commonJSWhitelist } = config.optimizeDeps || {}

// Determine deps to optimize. The goal is to only pre-bundle deps that falls
// under one of the following categories:
// 1. Is CommonJS module
// 2. Has imports to relative files (e.g. lodash-es, lit-html)
// 3. Has imports to bare modules that are not in the project's own deps
// 1. Has imports to relative files (e.g. lodash-es, lit-html)
// 2. Has imports to bare modules that are not in the project's own deps
// (i.e. esm that imports its own dependencies, e.g. styled-components)
await init
const cjsDeps: string[] = []
const qualifiedDeps = deps.filter((id) => {
console.log(id)
if (include && !include.includes(id)) {
debug(`skipping ${id} (not included)`)
return false
Expand All @@ -103,25 +106,32 @@ export async function optimizeDeps(
debug(`skipping ${id} (excluded)`)
return false
}
if (commonJSWhitelist && commonJSWhitelist.includes(id)) {
debug(`optimizing ${id} (commonJSWhitelist)`)
return true
}
if (KNOWN_IGNORE_LIST.has(id)) {
debug(`skipping ${id} (internal excluded)`)
return false
}
const entry = resolveNodeModuleEntry(root, id)
if (!entry) {
const pkgInfo = resolveNodeModuleEntry(root, id)
if (!pkgInfo) {
debug(`skipping ${id} (cannot resolve entry)`)
return false
}
const [entry, pkg] = pkgInfo
if (!supportedExts.includes(path.extname(entry))) {
debug(`skipping ${id} (entry is not js)`)
return false
}
const content = fs.readFileSync(resolveFrom(root, entry), 'utf-8')
const [imports, exports] = parse(content)
if (!exports.length) {
debug(`optimizing ${id} (no exports, likely commonjs)`)
// no exports, likely a commonjs module
return true
if (!exports.length && !/export\s+\*\s+from/.test(content)) {
if (!pkg.module) {
cjsDeps.push(id)
}
debug(`skipping ${id} (no exports, likely commonjs)`)
return false
}
for (const { s, e } of imports) {
let i = content.slice(s, e).trim()
Expand All @@ -139,8 +149,30 @@ export async function optimizeDeps(
})

if (!qualifiedDeps.length) {
await fs.writeFile(hashPath, depHash)
log(`No listed dependency requires optimization. Skipping.`)
if (!cjsDeps.length) {
await fs.writeFile(hashPath, depHash)
log(`No listed dependency requires optimization. Skipping.`)
} else {
console.error(
chalk.yellow(
`[vite] The following dependencies seem to be CommonJS modules that\n` +
`do not provide ESM-friendly file formats:\n\n ` +
cjsDeps.map((dep) => chalk.magenta(dep)).join(`\n `) +
`\n` +
`\n- If you are not using them in browser code, you can move them\n` +
`to devDependencies or exclude them from this check by adding\n` +
`them to ${chalk.cyan(
`optimizeDeps.exclude`
)} in vue.config.js.\n` +
`\n- If you do intend to use them in the browser, you can try adding\n` +
`them to ${chalk.cyan(
`optimizeDeps.commonJSWhitelist`
)} in vue.config.js but they\n` +
`may fail to bundle or work properly. Consider choosing more modern\n` +
`alternatives that provide ES module build formts.`
)
)
}
return
}

Expand Down
14 changes: 8 additions & 6 deletions src/node/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ export function resolveBareModule(root: string, id: string, importer: string) {
if (optimized) {
return id
}
const nodeEntry = resolveNodeModuleEntry(root, id)
if (nodeEntry) {
return nodeEntry
const pkgInfo = resolveNodeModuleEntry(root, id)
if (pkgInfo) {
return pkgInfo[0]
}
const deepMatch = id.match(deepImportRE)
if (deepMatch) {
Expand Down Expand Up @@ -162,7 +162,7 @@ export function resolveOptimizedModule(
}
}

const nodeModulesEntryMap = new Map()
const nodeModulesEntryMap = new Map<string, [string, any]>()

export function resolveNodeModuleEntry(root: string, id: string) {
const cached = nodeModulesEntryMap.get(id)
Expand Down Expand Up @@ -195,8 +195,10 @@ export function resolveNodeModuleEntry(root: string, id: string) {
}
entryPoint = path.posix.join(id, '/', entryPoint!)
debug(`(node_module entry) ${id} -> ${entryPoint}`)
nodeModulesEntryMap.set(id, entryPoint)
return entryPoint

const result: [string, any] = [entryPoint, pkg]
nodeModulesEntryMap.set(id, result)
return result
}
}

Expand Down

0 comments on commit 0e68cc1

Please sign in to comment.