// webpack.config.js
module.exports = {
// 入口
entry: './src/index.js',
// 输出
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
},
// 模式
mode: 'production', // development | production
// 加载器
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
// 插件
plugins: [
new HtmlWebpackPlugin({ template: './index.html' }),
new MiniCssExtractPlugin()
],
// 优化
optimization: {
splitChunks: {
chunks: 'all'
}
}
};
| Loader | 作用 |
|---|
| babel-loader | 转译 ES6+ |
| css-loader | 解析 CSS |
| style-loader | 注入 CSS 到 DOM |
| sass-loader | 编译 Sass |
| file-loader | 处理文件 |
| url-loader | 小文件转 base64 |
| Plugin | 作用 |
|---|
| HtmlWebpackPlugin | 生成 HTML |
| MiniCssExtractPlugin | 提取 CSS |
| CleanWebpackPlugin | 清理目录 |
| DefinePlugin | 定义环境变量 |
| CopyWebpackPlugin | 复制文件 |
module.exports = {
optimization: {
// 代码分割
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
},
// 提取 runtime
runtimeChunk: 'single',
// Tree Shaking
usedExports: true,
// 压缩
minimize: true,
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin()
]
}
};
- 开发时使用原生 ESM,无需打包
- 生产环境使用 Rollup 打包
- 极快的冷启动和热更新
// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': '/src'
}
},
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
},
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router']
}
}
}
}
});
<!-- 预加载 -->
<link rel="preload" href="critical.js" as="script">
<!-- 预获取 -->
<link rel="prefetch" href="next-page.js">
<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="//api.example.com">
// 1. 路由懒加载
const Home = () => import('./views/Home.vue');
// 2. 组件懒加载
const AsyncComponent = defineAsyncComponent(() => import('./Async.vue'));
// 3. 图片懒加载
<img loading="lazy" src="image.jpg">
// 4. Tree Shaking
import { debounce } from 'lodash-es'; // 按需引入
// 文件名 hash
output: {
filename: '[name].[contenthash].js'
}
// HTTP 缓存
// 静态资源:Cache-Control: max-age=31536000
// HTML:Cache-Control: no-cache
| 指标 | 说明 | 目标 |
|---|
| FCP | 首次内容绘制 | < 1.8s |
| LCP | 最大内容绘制 | < 2.5s |
| FID | 首次输入延迟 | < 100ms |
| CLS | 累积布局偏移 | < 0.1 |
| TTI | 可交互时间 | < 3.8s |
// 导出
export const name = 'module';
export default function() {}
// 导入
import { name } from './module';
import fn from './module';
import * as module from './module';
// 导出
module.exports = { name: 'module' };
exports.name = 'module';
// 导入
const module = require('./module');
| 特性 | ESM | CommonJS |
|---|
| 加载 | 编译时 | 运行时 |
| 输出 | 值的引用 | 值的拷贝 |
| 异步 | 支持 | 同步 |
| Tree Shaking | 支持 | 不支持 |
# npm
npm install package
npm install package --save-dev
# yarn
yarn add package
yarn add package --dev
# pnpm(推荐)
pnpm add package
pnpm add package -D
{
"name": "project",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"vue": "^3.0.0"
},
"devDependencies": {
"vite": "^4.0.0"
}
}
// .eslintrc.js
module.exports = {
extends: ['eslint:recommended', 'plugin:vue/vue3-recommended'],
rules: {
'no-console': 'warn',
'no-unused-vars': 'error'
}
};
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
}
// package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,vue}": ["eslint --fix", "prettier --write"]
}
}