#Vue CLI 配置
#依赖安装
安装全局插件
npm install -g @vue/cli
# or
yarn global add @vue/cli创建项目
vue create my-project
# or
vue ui package.json 启动命令配置
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
}
}- 配置文件
vue.config.js
serve 启动配置
用法:vue-cli-service serve [options] [entry]
选项:
--open 在服务器启动时打开浏览器
--copy 在服务器启动时将 URL 复制到剪切版
--mode 指定环境模式 (默认值:development)
--host 指定 host (默认值:0.0.0.0)
--port 指定 port (默认值:8080)
--https 使用 https (默认值:false)build 打包配置
用法:vue-cli-service build [options] [entry|pattern]
选项:
--mode 指定环境模式 (默认值:production)
--dest 指定输出目录 (默认值:dist)
--modern 面向现代浏览器带自动回退地构建应用
--target app | lib | wc | wc-async (默认值:app)
--name 库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名)
--no-clean 在构建项目之前不清除目标目录的内容
--report 生成 report.html 以帮助分析包内容
--report-json 生成 report.json 以帮助分析包内容
--watch 监听文件变化#打包配置
- 配置文件
babel.config.js
babel.config.js
module.exports = {
presets: [
"@vue/cli-plugin-babel/preset",
[
"@babel/preset-env",
{
modules: false,
},
],
],
compact: false,
plugins: [
[
"component",
// element-ui 按需加载
{
libraryName: "element-ui",
styleLibraryName: "theme-chalk",
},
],
],
env: {
development: {
// 组件动态导入配置 "@babel/plugin-syntax-dynamic-import"
plugins: ["dynamic-import-node"],
},
production: {
// 生产环境移除console
plugins: ["transform-remove-console"],
},
},
};babel 配置文件相关插件
@vue/cli-plugin-babel@babel/preset-env@babel/plugin-syntax-dynamic-importtransform-remove-console@babel/plugin-transform-runtime
- 配置文件
vue.config.js
vue.config.js
module.exports = {
// 忽略依赖包 babel 转码
transpileDependencies: true,
publicPath: "/",
outputDir: "dist",
assetsDir: "static",
// 代码检查
lintOnSave: isProd ? false : "warning",
// 打包代码不生成 source map
productionSourceMap: false,
devServer: {
host: "0.0.0.0",
port: 8080,
// 浏览器热更新
hot: true,
compress: true,
proxy: {
// 代理API置
[process.env.VUE_APP_API]: {
target: "http://localhost:8080",
changeOrigin: true,
pathRewrite: {
["^" + process.env.VUE_APP_API]: "",
},
},
},
client: {
// 浏览器控制台错误提示
overlay: false,
// 进度条
progress: true,
},
},
css: {
loaderOptions: {
sass: {
// 全局变量 scss 文件引入
additionalData: `@import "~@/assets/css/variables.scss";`,
sassOptions: { outputStyle: "expanded" },
},
},
},
};vue.config.js
// 打包压缩插件
const CompressionWebpackPlugin = require("compression-webpack-plugin");
module.exports = defineConfig({
configureWebpack: {
// externals: {
// vue: "Vue",
// vuex: "Vuex",
// axios: "axios",
// "vue-router": "VueRouter",
// "element-ui": "ELEMENT"
// } /* CDN */,
cache: {
type: "filesystem",
allowCollectingMemory: isProd ? false : true,
},
target: isProd ? "browserslist" : "web",
name: name,
performance: {
hints: false,
},
plugins: [
new CompressionWebpackPlugin({
algorithm: "gzip",
filename: "[path][base].gz",
test: /\.(js|css|json|html)(\?.*)?$/i,
threshold: 10240,
minRatio: 0.8,
}),
],
},
});- chainWebpack 配置
vue.config.js
const { defineConfig } = require("@vue/cli-service");
// 打包优化插件
const { ESBuildMinifyPlugin } = require("esbuild-loader");
// 代码跳转编辑器插件
const { codeInspectorPlugin } = require("code-inspector-plugin");
// 是否生产环境
const isProd = process.env.NODE_ENV === "production";
// 代码跳转编辑器配置
const devCIP = codeInspectorPlugin({
bundler: "webpack",
hideConsole: true,
hideDomPathAttr: true,
});
module.exports = defineConfig({
chainWebpack: (config) => {
if (isProd) {
// 删除预加载文件
config.plugins.delete("preload");
config.plugins.delete("prefetch");
// 打包优化
const rule = config.module.rule("js");
rule.uses.clear();
rule.use("esbuild-loader").loader("esbuild-loader");
config.optimization.minimizers.delete("terser");
config.optimization
.minimizer("esbuild")
.use(ESBuildMinifyPlugin, [{ minify: true, css: true }]);
}
if (process.env.NODE_ENV === "development")
config.plugin("code-inspector-plugin").use(devCIP);
// 打包分片
config.when(process.env.NODE_ENV == "production", (config) => {
config.optimization.splitChunks({
chunks: "all",
cacheGroups: {
vendors: {
name: "chunk-vendors",
chunks: "initial",
test: /[\\/]node_modules[\\/]/,
priority: 1,
},
elementUI: {
name: "chunk-elementUI",
priority: 2,
test: /[\\/]node_modules[\\/]_?element-ui(.*)/,
reuseExistingChunk: true,
},
common: {
name: "chunk-common",
chunks: "all",
test: /[\\/]src[\\/]/,
minSize: 0,
minChunks: 2,
priority: 1,
reuseExistingChunk: true,
},
styles: {
name: "styles",
test: /\.(s?css|less|sass)$/,
chunks: "all",
enforce: true,
},
},
});
config.optimization.runtimeChunk("single");
});
},
});webpack 配置
#完整配置
vue.config.js 完整配置
const { defineConfig } = require("@vue/cli-service");
// 打包优化插件
const { ESBuildMinifyPlugin } = require("esbuild-loader");
// 代码跳转编辑器插件
const { codeInspectorPlugin } = require("code-inspector-plugin");
// 打包压缩插件
const CompressionWebpackPlugin = require("compression-webpack-plugin");
// 网站名称配置
const name = process.env.VUE_APP_TITLE;
// 是否生产环境
const isProd = process.env.NODE_ENV === "production";
// 代码跳转编辑器配置
const devCIP = codeInspectorPlugin({
bundler: "webpack",
hideConsole: true,
hideDomPathAttr: true,
});
module.exports = defineConfig({
transpileDependencies: true,
publicPath: "/",
outputDir: "dist",
assetsDir: "static",
lintOnSave: isProd ? false : "warning",
productionSourceMap: false,
devServer: {
host: "0.0.0.0",
port: 8080,
hot: true,
compress: true,
proxy: {
[process.env.VUE_APP_API]: {
target: "http://localhost:8080",
changeOrigin: true,
pathRewrite: {
["^" + process.env.VUE_APP_API]: "",
},
},
},
client: {
overlay: false,
progress: true,
},
},
css: {
loaderOptions: {
sass: {
additionalData: `@import "~@/assets/css/variables.scss";`,
sassOptions: { outputStyle: "expanded" },
},
},
},
chainWebpack: (config) => {
if (isProd) {
// 删除预加载文件
config.plugins.delete("preload");
config.plugins.delete("prefetch");
// 打包优化
const rule = config.module.rule("js");
rule.uses.clear();
rule.use("esbuild-loader").loader("esbuild-loader");
config.optimization.minimizers.delete("terser");
config.optimization
.minimizer("esbuild")
.use(ESBuildMinifyPlugin, [{ minify: true, css: true }]);
}
if (process.env.NODE_ENV === "development")
config.plugin("code-inspector-plugin").use(devCIP);
// 打包分片
config.when(process.env.NODE_ENV == "production", (config) => {
config.optimization.splitChunks({
chunks: "all",
cacheGroups: {
vendors: {
name: "chunk-vendors",
chunks: "initial",
test: /[\\/]node_modules[\\/]/,
priority: 1,
},
elementUI: {
name: "chunk-elementUI",
priority: 2,
test: /[\\/]node_modules[\\/]_?element-ui(.*)/,
reuseExistingChunk: true,
},
common: {
name: "chunk-common",
chunks: "all",
test: /[\\/]src[\\/]/,
minSize: 0,
minChunks: 2,
priority: 1,
reuseExistingChunk: true,
},
styles: {
name: "styles",
test: /\.(s?css|less|sass)$/,
chunks: "all",
enforce: true,
},
},
});
config.optimization.runtimeChunk("single");
});
},
configureWebpack: {
// externals: {
// vue: "Vue",
// vuex: "Vuex",
// axios: "axios",
// "vue-router": "VueRouter",
// "element-ui": "ELEMENT"
// } /* CDN */,
cache: {
type: "filesystem",
allowCollectingMemory: isProd ? false : true,
},
target: isProd ? "browserslist" : "web",
name: name,
performance: {
hints: false,
},
plugins: [
new CompressionWebpackPlugin({
algorithm: "gzip",
filename: "[path][base].gz",
test: /\.(js|css|json|html)(\?.*)?$/i,
threshold: 10240,
minRatio: 0.8,
}),
],
},
});打包配置总结
- 打包输出目录设置
publicPath: 设置静态资源路径,如:/staticoutputDir: 设置打包输出目录,如:dist、build、outputassetsDir: 设置静态资源目录,如:static、assets、publiclintOnSave: 是否开启 eslint 语法检查,默认为true,可以设置为false或warningdevServer: 开发环境配置,如:host、port、hot、compress、proxy、clientcss: 设置 css 配置,如:loaderOptionschainWebpack: 链式配置,可以添加、删除、修改 webpack 配置,如:externals、splitChunks、runtimeChunk、plugin等
#四、CDN 与 externals 减包
若打包后 vendor.*.js 体积过大导致首屏偏慢,可把 vue、element-ui、vue-router、axios 等稳定依赖改为 CDN 引入,并在构建配置中标记为外部依赖,使其不进入产物。
首先在页面模板中引入 CDN 链接:
index.html
<script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.staticfile.org/element-ui/2.10.1/index.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.0.7/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.19.0/axios.min.js"></script>Vue CLI 2.x 项目在 webpack.base.conf.js 中配置 externals:
webpack.base.conf.js
module.exports = {
// 配置 cdn 包
externals: {
vue: "Vue",
element: "element-ui",
"vue-router": "VueRouter",
axios: "axios",
},
};Vue CLI 3.x 及以上项目,在 vue.config.js 中通过 configureWebpack 配置:
vue.config.js
module.exports = {
configureWebpack: {
externals: {
vue: "Vue",
element: "ELEMENT",
"vue-router": "VueRouter",
axios: "axios",
},
},
};小结
- 通过 CDN 链接方式加载依赖,可以显著减少打包产物的文件大小;
- 采用 CDN 后需注掉对应的
import XXX from 'XXX'与Vue.use(xxx),否则仍会被打包; - 内网或离线部署场景不建议使用 CDN,改为拆分
vendor或开启 gzip 压缩。
#参考文档
Vue CLI 官方文档「👈 点击查阅」