Skip to content

Commit

Permalink
feat: auto inject hmr client
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Apr 20, 2020
1 parent 820c2cf commit 4a04d81
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 16 deletions.
4 changes: 2 additions & 2 deletions lib/hmrProxy.js → lib/hmrClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ socket.addEventListener('message', ({ data }) => {
case 'reload':
import(`${path}?t=${Date.now()}`).then(m => {
__VUE_HMR_RUNTIME__.reload(path, m.default)
console.log(`[vds][hmr] ${path} reloaded.`)
console.log(`[vds] ${path} reloaded.`)
})
break
case 'rerender':
import(`${path}?type=template&t=${Date.now()}`).then(m => {
__VUE_HMR_RUNTIME__.rerender(path, m.render)
console.log(`[vds][hmr] ${path} template updated.`)
console.log(`[vds] ${path} template updated.`)
})
break
case 'update-style':
Expand Down
10 changes: 5 additions & 5 deletions lib/fileWatcher.js → lib/hmrWatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ exports.createFileWatcher = (notify) => {
})

fileWatcher.on('change', (file) => {
const resourcePath = '/' + path.relative(process.cwd(), file)

if (file.endsWith('.vue')) {
// check which part of the file changed
const [descriptor, prevDescriptor] = parseSFC(file)
const resourcePath = '/' + path.relative(process.cwd(), file)

if (!prevDescriptor) {
// the file has never been accessed yet
return
Expand All @@ -23,7 +23,7 @@ exports.createFileWatcher = (notify) => {
(descriptor.script && descriptor.script.content) !==
(prevDescriptor.script && prevDescriptor.script.content)
) {
console.log(`[hmr] <script> for ${resourcePath} changed. Triggering component reload.`)
console.log(`[hmr:reload] ${resourcePath}`)
notify({
type: 'reload',
path: resourcePath
Expand All @@ -35,7 +35,7 @@ exports.createFileWatcher = (notify) => {
(descriptor.template && descriptor.template.content) !==
(prevDescriptor.template && prevDescriptor.template.content)
) {
console.log(`[hmr] <template> for ${resourcePath} changed. Triggering component re-render.`)
console.log(`[hmr:rerender] ${resourcePath}`)
notify({
type: 'rerender',
path: resourcePath
Expand All @@ -45,7 +45,7 @@ exports.createFileWatcher = (notify) => {

// TODO styles
} else {
console.log(`[hmr] script file ${resourcePath} changed. Triggering full page reload.`)
console.log(`[hmr:full-reload] ${resourcePath}`)
notify({
type: 'full-reload'
})
Expand Down
6 changes: 4 additions & 2 deletions lib/parseSFC.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { parse } = require('@vue/compiler-sfc')

const cache = new Map()

exports.parseSFC = filename => {
exports.parseSFC = (filename, saveCache = false) => {
const content = fs.readFileSync(filename, 'utf-8')
const { descriptor, errors } = parse(content, {
filename
Expand All @@ -14,6 +14,8 @@ exports.parseSFC = filename => {
}

const prev = cache.get(filename)
cache.set(filename, descriptor)
if (saveCache) {
cache.set(filename, descriptor)
}
return [descriptor, prev]
}
14 changes: 9 additions & 5 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ const url = require('url')
const ws = require('ws')
const serve = require('serve-handler')
const vue = require('./vueMiddleware')
const { createFileWatcher } = require('./fileWatcher')
const { createFileWatcher } = require('./hmrWatcher')
const { sendJS } = require('./utils')

const hmrProxy = fs.readFileSync(path.resolve(__dirname, './hmrProxy.js'))
const hmrClientCode = fs.readFileSync(path.resolve(__dirname, './hmrClient.js'))

const server = http.createServer((req, res) => {
const pathname = url.parse(req.url).pathname
if (pathname === '/__hmrProxy') {
sendJS(res, hmrProxy)
if (pathname === '/__hmrClient') {
sendJS(res, hmrClientCode)
} else if (pathname.endsWith('.vue')) {
vue(req, res)
} else {
serve(req, res)
serve(req, res, {
rewrites: [
{ source: '**', destination: '/index.html' }
]
})
}
})

Expand Down
11 changes: 9 additions & 2 deletions lib/vueMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ module.exports = (req, res) => {
const parsed = url.parse(req.url, true)
const query = parsed.query
const filename = path.join(process.cwd(), parsed.pathname.slice(1))
const [descriptor] = parseSFC(filename)
const [descriptor] = parseSFC(
filename,
true /* save last accessed descriptor on the client */
)
if (!query.type) {
let code = ``
// inject hmr client
let code = `import "/__hmrClient"\n`
// TODO use more robust rewrite
if (descriptor.script) {
code += descriptor.script.content.replace(
`export default`,
'const script ='
)
code += `\nexport default script`
} else {
code += `const script = {}; export default script`
}
if (descriptor.template) {
code += `\nimport { render } from ${JSON.stringify(
Expand All @@ -39,6 +45,7 @@ module.exports = (req, res) => {
source: descriptor.template.content,
filename,
compilerOptions: {
// TODO infer proper Vue path
runtimeModuleName: '/vue.js'
}
})
Expand Down

0 comments on commit 4a04d81

Please sign in to comment.