使用node实现简易版本的vite加载器
代码实现
const Koa = require('koa')
const fs = require('fs')
const path = require('path')
const app = new Koa()
// 解析 vue,生成对应的template,srcipt,css
const compilerSFC = require('@vue/compiler-sfc')
// 解析dom
const compilerDOM = require('@vue/compiler-dom')
app.use(async ctx => {
const {
url,
query
} = ctx.request
// 加载html
if (url === '/') {
ctx.type = 'text/html'
ctx.body = fs.readFileSync(path.join(__dirname, './index.html'), 'utf8')
} else if (url.endsWith('.js')) {
// 加载js
const p = path.join(__dirname, url)
ctx.type = 'application/javascript'
ctx.body = rewriteImport(fs.readFileSync(p, 'utf8'))
} else if (url.startsWith('/@modules/')) {
// 加载模块包
const moduleName = url.replace('/@modules/', '')
const prefix = path.join(__dirname, '../node_modules', moduleName)
const module = require(prefix + '/package.json').module
const filePath = path.join(prefix, module)
const ret = fs.readFileSync(filePath, 'utf8')
ctx.type = 'application/javascript'
ctx.body = rewriteImport(ret)
} else if (url.indexOf('.vue') > -1) {
// 加载vue文件
const p = path.join(__dirname, url.split('?')[0])
const ret = compilerSFC.parse(fs.readFileSync(p, 'utf8'))
if (!query.type) {
// 加载vue中的script,添加render函数
const srciptContent = ret.descriptor.script.content
const script = srciptContent.replace('export default ', 'const __script= ')
ctx.type = 'application/javascript'
ctx.body = `
${ rewriteImport(script)}
// 解析tpl
import { render as __render } from '${url}?type=template'
__script.render = __render
export default __script
`
} else if (query.type === 'template') {
// 返回html
const tpl = ret.descriptor.template.content
const render = compilerDOM.compile(tpl, {
mode: 'module'
}).code
ctx.type = 'application/javascript'
ctx.body = rewriteImport(render)
}
}
})
// 重写import 方法
function rewriteImport(content) {
return content.replace(/ from ['"](.*)['"]/g, function (s1, s2) {
if (s2.startsWith('./') || s2.startsWith('../') || s2.startsWith('/')) {
// 加载模块
return s1
} else {
// 加载模块包
return ` from '/@modules/${s2}' `
}
})
}
app.listen(8000, () => {
console.log('vite start')
})
文章目录