Skip to content

Commit

Permalink
refactor: use /@ for special requests
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Apr 23, 2020
1 parent a183791 commit ae3c83a
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 38 deletions.
10 changes: 10 additions & 0 deletions src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,13 @@ export function updateStyle(id: string, url: string) {
}
link.setAttribute('href', url)
}

export const hot = {
accept(
boundaryUrl: string,
deps: string[],
callback: (modules: object[]) => void
) {
// TODO
}
}
62 changes: 35 additions & 27 deletions src/server/plugins/hmr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { parseSFC, vueCache } from './vue'
import { cachedRead } from '../utils'
import { importerMap } from './modules'

const hmrClientPath = path.resolve(__dirname, '../../client/client.js')
const hmrClientFilePath = path.resolve(__dirname, '../../client/client.js')
export const hmrClientPublicPath = '/@hmr'

interface HMRPayload {
type: string
Expand All @@ -19,11 +20,11 @@ interface HMRPayload {

export const hmrPlugin: Plugin = ({ root, app, server }) => {
app.use(async (ctx, next) => {
if (ctx.path !== '/__hmrClient') {
if (ctx.path !== hmrClientPublicPath) {
return next()
}
ctx.type = 'js'
ctx.body = await cachedRead(hmrClientPath)
ctx.body = await cachedRead(hmrClientFilePath)
})

// start a websocket server to send hmr notifications to the client
Expand Down Expand Up @@ -59,33 +60,40 @@ export const hmrPlugin: Plugin = ({ root, app, server }) => {
if (file.endsWith('.vue')) {
handleVueSFCReload(file, servedPath)
} else {
// normal js file
const importers = importerMap.get(servedPath)
if (importers) {
const vueImporters = new Set<string>()
const jsHotImporters = new Set<string>()
const hasDeadEnd = walkImportChain(
importers,
vueImporters,
jsHotImporters
)

if (hasDeadEnd) {
handleJSReload(servedPath)
}
})

function handleJSReload(servedPath: string) {
// normal js file
const importers = importerMap.get(servedPath)
if (importers) {
const vueImporters = new Set<string>()
const jsHotImporters = new Set<string>()
const hasDeadEnd = walkImportChain(
importers,
vueImporters,
jsHotImporters
)

if (hasDeadEnd) {
notify({
type: 'full-reload'
})
} else {
vueImporters.forEach((vueImporter) => {
notify({
type: 'full-reload'
})
} else {
vueImporters.forEach((vueImporter) => {
notify({
type: 'reload',
path: vueImporter
})
type: 'reload',
path: vueImporter
})
console.log(jsHotImporters)
}
})
jsHotImporters.forEach((jsImporter) => {
// TODO
console.log(jsImporter)
})
}
}
})
}

function walkImportChain(
currentImporters: Set<string>,
Expand Down Expand Up @@ -116,7 +124,7 @@ export const hmrPlugin: Plugin = ({ root, app, server }) => {

function isHotBoundary(servedPath: string): boolean {
// TODO
return false
return true
}

async function handleVueSFCReload(file: string, servedPath: string) {
Expand Down
22 changes: 13 additions & 9 deletions src/server/plugins/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import { init as initLexer, parse } from 'es-module-lexer'
import MagicString from 'magic-string'
import { cachedRead } from '../utils'
import { promises as fs } from 'fs'
import { hmrClientPublicPath } from './hmr'

const idToFileMap = new Map()
const fileToIdMap = new Map()
const webModulesMap = new Map()

export const modulesPlugin: Plugin = ({ root, app }) => {
// rewrite named module imports to `/__modules/:id` requests
// rewrite named module imports to `/@modules/:id` requests
app.use(async (ctx, next) => {
await next()

Expand All @@ -37,8 +38,8 @@ export const modulesPlugin: Plugin = ({ root, app }) => {
// regardless of the extension of the original files.
if (
ctx.response.is('js') &&
// skip dependency modules
!ctx.path.startsWith(`/__`) &&
// skip special requests (internal scripts & module redirects)
!ctx.path.startsWith(`/@`) &&
// only need to rewrite for <script> part in vue files
!(ctx.path.endsWith('.vue') && ctx.query.type != null)
) {
Expand All @@ -51,8 +52,8 @@ export const modulesPlugin: Plugin = ({ root, app }) => {
}
})

// handle /__modules/:id requests
const moduleRE = /^\/__modules\//
// handle /@modules/:id requests
const moduleRE = /^\/@modules\//
app.use(async (ctx, next) => {
if (!moduleRE.test(ctx.path)) {
return next()
Expand Down Expand Up @@ -175,6 +176,7 @@ async function resolveWebModule(
// so that we can determine what files to hot reload
export const importerMap = new Map<string, Set<string>>()
export const importeeMap = new Map<string, Set<string>>()
export const hotBoundariesMap = new Map<string, Set<string>>()

function rewriteImports(source: string, importer: string, timestamp?: string) {
try {
Expand All @@ -190,11 +192,12 @@ function rewriteImports(source: string, importer: string, timestamp?: string) {

imports.forEach(({ s: start, e: end, d: dynamicIndex }) => {
const id = source.substring(start, end)
if (dynamicIndex < 0) {
if (dynamicIndex === -1) {
if (/^[^\/\.]/.test(id)) {
s.overwrite(start, end, `/__modules/${id}`)
s.overwrite(start, end, `/@modules/${id}`)
hasReplaced = true
} else if (importer && !id.startsWith(`/__`)) {
} else if (id === hmrClientPublicPath) {
} else {
// force re-fetch all imports by appending timestamp
// if this is a hmr refresh request
if (timestamp) {
Expand All @@ -215,7 +218,7 @@ function rewriteImports(source: string, importer: string, timestamp?: string) {
}
importers.add(importer)
}
} else {
} else if (dynamicIndex >= 0) {
// TODO dynamic import
}
})
Expand All @@ -238,6 +241,7 @@ function rewriteImports(source: string, importer: string, timestamp?: string) {

return source
} catch (e) {
debugger
console.error(`Error: module imports rewrite failed for source:\n`, source)
return source
}
Expand Down
5 changes: 3 additions & 2 deletions src/server/plugins/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { resolveCompiler } from '../resolveVue'
import hash_sum from 'hash-sum'
import { cachedRead } from '../utils'
import LRUCache from 'lru-cache'
import { hmrClientPublicPath } from './hmr'

interface CacheEntry {
descriptor?: SFCDescriptor
Expand Down Expand Up @@ -119,7 +120,7 @@ function compileSFCMain(

timestamp = timestamp ? `&t=${timestamp}` : ``
// inject hmr client
let code = `import { updateStyle } from "/__hmrClient"\n`
let code = `import { updateStyle } from "${hmrClientPublicPath}"\n`
if (descriptor.script) {
code += descriptor.script.content.replace(
`export default`,
Expand Down Expand Up @@ -175,7 +176,7 @@ function compileSFCTemplate(
filename,
compilerOptions: {
scopeId: scoped ? `data-v-${hash_sum(pathname)}` : null,
runtimeModuleName: '/__modules/vue'
runtimeModuleName: '/@modules/vue'
}
})

Expand Down

0 comments on commit ae3c83a

Please sign in to comment.