Skip to content

Commit

Permalink
fix(hmr): fix hot.accept() module resolution (#97)
Browse files Browse the repository at this point in the history
  • Loading branch information
bates64 authored May 9, 2020
1 parent b7f5ad2 commit 7ffa9c0
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 29 deletions.
10 changes: 8 additions & 2 deletions src/node/server/serverPluginHmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ import chalk from 'chalk'
import hash_sum from 'hash-sum'
import { SFCBlock } from '@vue/compiler-sfc'
import { parseSFC, vueCache, srcImportMap } from './serverPluginVue'
import { cachedRead } from '../utils'
import { cachedRead, resolveImport } from '../utils'
import { FSWatcher } from 'chokidar'
import MagicString from 'magic-string'
import { parse } from '@babel/parser'
import { StringLiteral, Statement, Expression } from '@babel/types'
import { InternalResolver } from '../resolver'

export const debugHmr = require('debug')('vite:hmr')

Expand Down Expand Up @@ -335,6 +336,7 @@ export function ensureMapEntry(map: HMRStateMap, key: string): Set<string> {
export function rewriteFileWithHMR(
source: string,
importer: string,
resolver: InternalResolver,
s: MagicString
) {
const ast = parse(source, {
Expand All @@ -351,7 +353,11 @@ export function rewriteFileWithHMR(

const registerDep = (e: StringLiteral) => {
const deps = ensureMapEntry(hmrAcceptanceMap, importer)
const depPublicPath = slash(path.resolve(path.dirname(importer), e.value))
const depPublicPath = slash(
path.isAbsolute(e.value)
? e.value
: resolveImport({ importer, id: e.value, resolver })
)
deps.add(depPublicPath)
debugHmr(` ${importer} accepts ${depPublicPath}`)
s.overwrite(e.start!, e.end!, JSON.stringify(depPublicPath))
Expand Down
30 changes: 3 additions & 27 deletions src/node/server/serverPluginModuleRewrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,7 @@ import {
hmrClientPublicPath,
hmrClientId
} from './serverPluginHmr'
import {
readBody,
cleanUrl,
isExternalUrl,
resolveRelativeRequest
} from '../utils'
import { readBody, cleanUrl, isExternalUrl, resolveImport } from '../utils'
import chalk from 'chalk'

const debug = require('debug')('vite:rewrite')
Expand Down Expand Up @@ -181,31 +176,12 @@ function rewriteImports(
if (!/.vue$|.vue\?type=/.test(importer)) {
// the user explicit imports the HMR API in a js file
// making the module hot.
rewriteFileWithHMR(source, importer, s)
rewriteFileWithHMR(source, importer, resolver, s)
// we rewrite the hot.accept call
hasReplaced = true
}
} else if (/^[^\/\.]/.test(id)) {
resolved = resolver.idToRequest(id) || `/@modules/${id}`
} else {
let { pathname, query } = resolveRelativeRequest(importer, id)
// append .js or .ts for extension-less imports
// for now we don't attemp to resolve other extensions
if (!/\.\w+$/.test(pathname)) {
const file = resolver.requestToFile(pathname)
const indexMatch = file.match(/\/index\.\w+$/)
if (indexMatch) {
pathname = pathname.replace(/\/(index)?$/, '') + indexMatch[0]
} else {
pathname += path.extname(file)
}
}
// force re-fetch all imports by appending timestamp
// if this is a hmr refresh request
if (timestamp) {
query += `${query ? `&` : `?`}t=${timestamp}`
}
resolved = pathname + query
resolved = resolveImport({ importer, id, resolver, timestamp })
}

if (resolved !== id) {
Expand Down
38 changes: 38 additions & 0 deletions src/node/utils/pathUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Context } from 'koa'
import path from 'path'
import slash from 'slash'
import { InternalResolver } from '../resolver'

export const queryRE = /\?.*$/
export const hashRE = /\#.*$/
Expand Down Expand Up @@ -48,3 +49,40 @@ export const isImportRequest = (ctx: Context): boolean => {
const referer = ctx.get('referer').replace(timeStampRE, '')
return jsSrcFileRE.test(referer)
}

const moduleRE = /^[^\/\.]/
const fileExtensionRE = /\.\w+$/

export const resolveImport = ({
importer,
id,
resolver,
timestamp
}: {
importer: string
id: string
resolver: InternalResolver
timestamp?: string
}): string => {
if (moduleRE.test(id)) {
return resolver ? resolver.idToRequest(id) || `/@modules/${id}` : id
} else {
let { pathname, query } = resolveRelativeRequest(importer, id)
// append an extension to extension-less imports
if (!fileExtensionRE.test(pathname)) {
const file = resolver.requestToFile(pathname)
const indexMatch = file.match(/\/index\.\w+$/)
if (indexMatch) {
pathname = pathname.replace(/\/(index)?$/, '') + indexMatch[0]
} else {
pathname += path.extname(file)
}
}
// force re-fetch all imports by appending timestamp
// if this is a hmr refresh request
if (timestamp) {
query += `${query ? `&` : `?`}t=${timestamp}`
}
return pathname + query
}
}

0 comments on commit 7ffa9c0

Please sign in to comment.