// config/cdn.js
const cdn = {
css: [
// 'https://cdn.jsdelivr.net/npm/vant@2.8/lib/index.css'
],
js: [
'https://cdn.bootcss.com/vue/2.5.2/vue.min.js',
'https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js',
'https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js'
]
}
module.exports = cdn
// webpack.config.js
plugins: [
new HtmlWebpackPlugin(Object.assign({
filename: 'index.html',
template: 'index.html',
inject: true
}, config.cdn))
]
<!--index.html-->
<body>
<div id="app">
<!-- shell -->
</div>
<script src="./static/js/axios.min.js"></script>
<% for (var i in htmlWebpackPlugin.options.js&&htmlWebpackPlugin.options.js) { %>
<script src="<%= htmlWebpackPlugin.options.js[i] %>"></script>
<% } %>
<!-- built files will be auto injected -->
</body>
VueCLI3打包优化--CDN
vue.config.js下的配置如下
externals: [ { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'element-ui': 'ELEMENT', 'echarts': 'echarts', 'vue-echarts': 'VueECharts', 'moment': 'moment', 'axios': 'axios', }, // vue-echarts引入的方式,需要如下去抽离 'echarts/lib/echarts', /^echarts\/lib\/chart\/.+$/i, /^echarts\/lib\/component\/.+$/i, ]
配置CDN
const cdn = { js: ['https://lib.baomitu.com/echarts/4.9.0-rc.1/echarts.min.js', 'https://lib.baomitu.com/vue-echarts/5.0.0-beta.0/vue-echarts.min.js', 'https://lib.baomitu.com/vue/2.6.10/vue.min.js', 'https://lib.baomitu.com/vuex/3.1.0/vuex.min.js', 'https://lib.baomitu.com/vue-router/3.0.6/vue-router.min.js', 'https://lib.baomitu.com/moment.js/2.29.1/moment.min.js', 'https://lib.baomitu.com/element-ui/2.15.1/index.min.js'], css: ['https://lib.baomitu.com/element-ui/2.15.1/theme-chalk/index.min.css'] } module.exports = { configureWebpack:{......}, chainWebpack(config) { config.plugin('html').tap(opts => { opts[0].cdn = cdn; return opts }) } }
可根据环境变量,仅在线上采取使用CDN,开发环境直接使用npm依赖包即可。
const IsProd= process.env.NODE_ENV === 'production'; chainWebpack(config) { if (IsProd) { config.plugin('html').tap(opts => { opts[0].cdn = cdn; return opts }) } }
3.index.html文件
<!DOCTYPE html> <html lang="en"> <!-- 使用CDN的CSS文件 --> <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style"> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet"> <% } %> <!-- 使用CDN的JS文件 --> <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %> <link href="<%= htmlWebpackPlugin.options.cdn.js[i] %>" rel="preload" as="script"> <% } %> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %> <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> <% } %> </body> </html>
使用 CDN 加速优化
const isProduction = process.env.NODE_ENV === 'production'; // externals const externals = { vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', vant: 'vant', axios: 'axios' } // CDN 外链,会插入到 index.html 中 const cdn = { // 开发环境 dev: { css: [], js: [] }, // 生产环境 build: { css: ['https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css'], js: [ 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js', 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js', 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js', 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js', 'https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js' ] } } module.exports = { configureWebpack: config => { // 为生产环境修改配置... if (isProduction) { // externals config.externals = externals } }, chainWebpack: config => { /** * 添加 CDN 参数到 htmlWebpackPlugin 配置中 */ config.plugin('html').tap(args => { if (isProduction) { args[0].cdn = cdn.build } else { args[0].cdn = cdn.dev } return args }) } }
<!-- 使用 CDN 的 CSS 文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
打包前的处理
build/utils.js添加读取事件
使用cdn其实也就是在webpack热启动和打包项目的时候动态插入script和style链接,为了方便维护,我们通过在build/utils.js文件上添加几个方法
1.添加cdn根地址
按照规律,得出cdn资源路径规则为
https://cdn.bootcss.com + 模块名 + 版本号 + 具体路径
// build/utils.js 国内免费cdn镜像源
exports.cdnBaseHttp = 'https://cdn.bootcss.com';
2.添加cdn模块 按照需要删改
// build/utils.js external配置
exports.externalConfig = [
{ name: 'vue', scope: 'Vue', js: 'vue.min.js' },
{ name: 'vue-router', scope: 'VueRouter', js: 'vue-router.min.js' },
{ name: 'axios', scope: 'axios', js: 'axios.min.js' },
{ name: 'element-ui', scope: 'ELEMENT', js: 'index.js', css: 'theme-chalk/index.css' },
];
name 模块名称,与package.json同名
scope 模块作用域命名
js js地址
css css地址
这里特别注意scope,它是webpack配置的external参数下的信息,比如vue的作用域命名是Vue,vue-router的作用域命名是VueRouter,element-ui的作用域命名是ELEMENT,同理,jq的作用域命名是JQuery,具体做法是先引入该资源,然后在控制台依次输入近似的值,一个个匹配(目前没找到更好的做法)。
3.添加获取版本号方法
// build/utils.js 获取模块版本号
exports.getModulesVersion = () => {
let mvs = {};
let regexp = /^npm_package_.{0,3}dependencies_/gi;
for (let m in process.env) { // 从node内置参数中读取,也可直接import 项目文件进来
if (regexp.test(m)) { // 匹配模块
// 获取到模块版本号
mvs[m.replace(regexp, '').replace(/_/g, '-')] = process.env[m].replace(/(~|\^)/g, '');
}
}
return mvs;
};
4.导出不需要被打包的cdn模块配置重点
// build/utils.js
exports.getExternalModules = config => {
let externals = {}; // 结果
let dependencieModules = this.getModulesVersion(); // 获取全部的模块和版本号
config = config || this.externalConfig; // 默认使用utils下的配置
config.forEach(item => { // 遍历配置
if (item.name in dependencieModules) {
let version = dependencieModules[item.name];
// 拼接css 和 js 完整链接
item.css = item.css && [this.cdnBaseHttp, item.name, version, item.css].join('/');
item.js = item.js && [this.cdnBaseHttp, item.name, version, item.js].join('/');
externals[item.name] = item.scope; // 为打包时准备
} else {
throw new Error('相关依赖未安装,请先执行npm install ' + item.name);
}
});
return externals;
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。