Skip to content

Commit

Permalink
feat: improve module resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed May 13, 2020
1 parent fa52279 commit 405f685
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 51 deletions.
41 changes: 25 additions & 16 deletions src/node/server/serverPluginModuleResolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import chalk from 'chalk'
import resolve from 'resolve-from'
import { ServerPlugin } from '.'
import { resolveVue, cachedRead } from '../utils'
import { URL } from 'url'

const debug = require('debug')('vite:resolve')

Expand Down Expand Up @@ -65,16 +66,19 @@ export const moduleResolvePlugin: ServerPlugin = ({ root, app, watcher }) => {
return serve(id, webModulePath, 'web_modules')
}

try {
// we land here after a module entry redirect
// or a direct deep import like 'foo/bar/baz.js'.
const file = resolve(root, id)
return serve(id, file, 'node_modules')
} catch (e) {
console.error(chalk.red(`[vite] Error while resolving /@modules/${id} :`))
console.error(e)
ctx.status = 404
const nodeModulePath = resolveNodeModule(root, id)
if (nodeModulePath) {
return serve(id, nodeModulePath, 'node_modules')
}

const importer = new URL(ctx.get('referer')).pathname
console.error(
chalk.red(
`[vite] Failed to resolve module import "${id}". ` +
`(imported by ${importer})`
)
)
ctx.status = 404
})
}

Expand All @@ -87,7 +91,7 @@ export function resolveBareModule(root: string, id: string) {
if (web) {
return id + '.js'
}
const nodeEntry = resolveNodeModuleEntry(root, id)
const nodeEntry = resolveNodeModule(root, id)
if (nodeEntry) {
return nodeEntry
}
Expand Down Expand Up @@ -129,10 +133,10 @@ export function resolveWebModule(root: string, id: string): string | undefined {
}
}

const idToEntryMap = new Map()
const nodeModulesMap = new Map()

function resolveNodeModuleEntry(root: string, id: string): string | undefined {
const cached = idToEntryMap.get(id)
function resolveNodeModule(root: string, id: string): string | undefined {
const cached = nodeModulesMap.get(id)
if (cached) {
return cached
}
Expand All @@ -144,11 +148,16 @@ function resolveNodeModuleEntry(root: string, id: string): string | undefined {
} catch (e) {}

if (pkgPath) {
// if yes, resolve entry file
// if yes, this is a entry import. resolve entry file
const pkg = require(pkgPath)
const entryPoint = id + '/' + (pkg.module || pkg.main || 'index.js')
const entryPoint = path.join(id, '/', pkg.module || pkg.main || 'index.js')
debug(`(node_module entry) ${id} -> ${entryPoint}`)
idToEntryMap.set(id, entryPoint)
nodeModulesMap.set(id, entryPoint)
return entryPoint
} else {
// possibly a deep import, try resolving directly
try {
return resolve(root, id)
} catch (e) {}
}
}
74 changes: 39 additions & 35 deletions src/node/server/serverPluginModuleRewrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ export const moduleRewritePlugin: ServerPlugin = ({
resolver,
config
}) => {
// bust module rewrite cache on file change
watcher.on('change', (file) => {
const publicPath = resolver.fileToRequest(file)
debug(`${publicPath}: cache busted`)
rewriteCache.del(publicPath)
})

// inject __DEV__ and process.env.NODE_ENV flags
// since some ESM builds expect these to be replaced by the bundler
const devInjectionCode =
Expand All @@ -67,6 +60,35 @@ export const moduleRewritePlugin: ServerPlugin = ({
const scriptRE = /(<script\b[^>]*>)([\s\S]*?)<\/script>/gm
const srcRE = /\bsrc=(?:"([^"]+)"|'([^']+)'|([^'"\s]+)\b)/

async function rewriteIndex(html: string) {
await initLexer
let hasInjectedDevFlag = false
const importer = '/index.html'
return html!.replace(scriptRE, (matched, openTag, script) => {
const devFlag = hasInjectedDevFlag ? `` : devInjectionCode
hasInjectedDevFlag = true
if (script) {
return `${devFlag}${openTag}${rewriteImports(
root,
script,
importer,
resolver
)}</script>`
} else {
const srcAttr = openTag.match(srcRE)
if (srcAttr) {
// register script as a import dep for hmr
const importee = cleanUrl(
slash(path.resolve('/', srcAttr[1] || srcAttr[2]))
)
debugHmr(` ${importer} imports ${importee}`)
ensureMapEntry(importerMap, importee).add(importer)
}
return `${devFlag}${matched}`
}
})
}

app.use(async (ctx, next) => {
await next()

Expand All @@ -75,37 +97,12 @@ export const moduleRewritePlugin: ServerPlugin = ({
}

if (ctx.path === '/index.html') {
const html = await readBody(ctx.body)
let html = await readBody(ctx.body)
if (html && rewriteCache.has(html)) {
debug('/index.html: serving from cache')
ctx.body = rewriteCache.get(html)
} else if (ctx.body) {
await initLexer
let hasInjectedDevFlag = false
const importer = '/index.html'
ctx.body = html!.replace(scriptRE, (matched, openTag, script) => {
const devFlag = hasInjectedDevFlag ? `` : devInjectionCode
hasInjectedDevFlag = true
if (script) {
return `${devFlag}${openTag}${rewriteImports(
root,
script,
importer,
resolver
)}</script>`
} else {
const srcAttr = openTag.match(srcRE)
if (srcAttr) {
// register script as a import dep for hmr
const importee = cleanUrl(
slash(path.resolve('/', srcAttr[1] || srcAttr[2]))
)
debugHmr(` ${importer} imports ${importee}`)
ensureMapEntry(importerMap, importee).add(importer)
}
return `${devFlag}${matched}`
}
})
} else if (html) {
ctx.body = await rewriteIndex(html)
rewriteCache.set(html, ctx.body)
return
}
Expand Down Expand Up @@ -142,6 +139,13 @@ export const moduleRewritePlugin: ServerPlugin = ({
debug(`(skipped) ${ctx.url}`)
}
})

// bust module rewrite cache on file change
watcher.on('change', (file) => {
const publicPath = resolver.fileToRequest(file)
debug(`${publicPath}: cache busted`)
rewriteCache.del(publicPath)
})
}

export function rewriteImports(
Expand Down

0 comments on commit 405f685

Please sign in to comment.