1. Vite概念:
2. Vite项目依赖:
compiler-sfc用来编译项目中的.vue结尾的单文件组件,在vue2中采用的vue-template-compliler
3. 基础使用:
vite serve / vite build
在运行vite serve
的时候不需要打包,直接开启一个web服务器,当浏览器请求服务器,比如请求一个单文件组件,这个时候在服务器端编译单文件组件,然后把编译的结果返回给浏览器,注意这里的编译是在服务器端,另外模块的处理是在请求到服务器端处理的。
而vue-cli-service serve
:
当运行vue-cli-service serve的时候,它内部会使用webpack,首先去打包所有的模块,如果模块数量比较多的话,打包速度会非常的慢,把打包的结果存储到内存中,然后才会开启开发的web服务器,浏览器请求web服务器,把内存中打包的结果直接返回给浏览器,像webpack这种工具,它的做法是将所有的模块提前编译打包进bundle里,也就是不管模块是否被执行,是否使用到,都要被编译和打包到bundle。随着项目越来越大,打包后的bundle也越来越大,打包的速度自然也就越来越慢。
Vite利用现代浏览器原生支持的ESModule这个模块化的特性省略了对模块的打包,对于需要编译的文件,比如单文件组件、样式模块等,vite采用的另一种模式即时编译,也就是说只有具体去请求某个文件的时候,才会在服务端编译这个文件,所以这种即时编译的好处主要体现在按需编译,速度会更快。
4. HMR:
5. Build:
6. 打包OR不打包:
8. 开箱即用:
9. Vite特性
#!/usr/bin/env node
const koa = require('koa');
const send = require('koa-send');
const app = new Koa();
// 1.静态文件服务器
app.use(async (ctx, next) => {
await send(ctx, ctx.path, { root: process.cwd(), index: 'index.html' });
await next();
})
app.listen(3000);
#!/usr/bin/env node
const koa = require('koa');
const send = require('koa-send');
const app = new Koa();
const streamToString = stream => new Promise((resolve, reject) => {
const chunks = [];
stream.on('data', (chunk) => {
chunks.push(chunk);
})
stream.on('end', () => {resolve(Buffer.concat(chunks).toString('utf-8'));});
stream.on('error', reject)
})
// 1.静态文件服务器
app.use(async (ctx, next) => {
await send(ctx, ctx.path, { root: process.cwd(), index: 'index.html' });
await next();
})
// 2.修改第三方模块的路径
app,use(async (ctx, next) => {
if(ctx.type === 'application/javascript') {
// import vue from 'vue'
// import App from './App.vue'
ctx.body = contents.replace(/(from\s+['"])/g, '$s1/@modules/')
}
})
app.listen(3000);
npm i @vue/compiler-sfc
#!/usr/bin/env node
const path = require('path')
const { Readable } = require('stream')
const Koa = require('koa')
const send = require('koa-send')
const compilerSFC = require('@vue/compiler-sfc')
const app = new Koa()
const streamToString = stream => new Promise((resolve, reject) => {
const chunks = []
stream.on('data', chunk => chunks.push(chunk))
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')))
stream.on('error', reject)
})
const stringToStream = text => {
const stream = new Readable()
stream.push(text)
stream.push(null)
return stream
}
// 3. 加载第三方模块
app.use(async (ctx, next) => {
// ctx.path --> /@modules/vue
if (ctx.path.startsWith('/@modules/')) {
const moduleName = ctx.path.substr(10)
const pkgPath = path.join(process.cwd(), 'node_modules', moduleName, 'package.json')
const pkg = require(pkgPath)
ctx.path = path.join('/node_modules', moduleName, pkg.module)
}
await next()
})
// 1. 静态文件服务器
app.use(async (ctx, next) => {
await send(ctx, ctx.path, { root: process.cwd(), index: 'index.html' })
await next()
})
// 4. 处理单文件组件
app.use(async (ctx, next) => {
if (ctx.path.endsWith('.vue')) {
const contents = await streamToString(ctx.body)
const { descriptor } = compilerSFC.parse(contents)
let code
if (!ctx.query.type) {
code = descriptor.script.content
// console.log(code)
code = code.replace(/export\s+default\s+/g, 'const __script = ')
code += `
import { render as __render } from "${ctx.path}?type=template"
__script.render = __render
export default __script
`
} else if (ctx.query.type === 'template') {
const templateRender = compilerSFC.compileTemplate({ source: descriptor.template.content })
code = templateRender.code
}
ctx.type = 'application/javascript'
ctx.body = stringToStream(code)
}
await next()
})
// 2. 修改第三方模块的路径
app.use(async (ctx, next) => {
if (ctx.type === 'application/javascript') {
const contents = await streamToString(ctx.body)
// import vue from 'vue'
// import App from './App.vue'
ctx.body = contents
.replace(/(from\s+['"])(?![\.\/])/g, '$1/@modules/')
.replace(/process\.env\.NODE_ENV/g, '"development"')
}
})
app.listen(3000)
console.log('Server running @ http://localhost:3000')
npm link
全局添加npm 包
如果不使用npm rm -g vite-cli
在vue目录里面启动命令: vite-cli