问题:使用cdn引入库是不是真的比npm引入的好?好在哪里?
场景:首屏加速,页面打开时更快。
原理:
页面里面有多少外链接资源文件,比如说链接引入的图片、css文件、js文件等。默认编译时会将所有的第三方的包打成一个chunk-vendors.js,浏览器的并发会限制同域资源的请求数的(一般是10个),如果第三方的包很多的话就会导致包很大网页首页加载的很慢很慢 所以可以将一些通用的,较大的包单独拎出来,从第三方的服务器加载,打破浏览器的并发限制,提高下载速度(浏览器引入网络资源的多线程的,js才是单线程的),防止自己的服务器带宽不够下载文件慢的问题。 如果没有多少资源文件的话,强行并发下载,会产生多线程小文件的I/O瓶颈。
按需引入的问题:如果只是按需引入了很少的依赖包也是没有必要用CDN引入的,因为根本问题是依赖包太大才需要用CDN的高带宽去解决。
cdn优势:
-
带宽更大引入时更快,加快首屏速度
-
不同地区用户访问可以就近加载。(如果自己的web站点带宽够大,全国甚至全球多低部署的话就没有必要用cdn了)
-
国内
- BootCdn网站 www.bootcdn.cn/
- 七牛云 staticfile.org/
-
国外
- unpkg网站 unpkg.comcdnjs
- 网站 www.jsdelivr.com/
总结:
在本地按需引入组件,然后使用cdn代理服务器将整个项目放上cdn代理服务器,这才是最优解。技能使用npm按需引入的优势,又可以享受CDN的优势。(这里还没有深入研究)
具体优化过程:
- 查看打包工具🔧
- 在终端运行
vue ui,会自动弹出浏览器,运行相应的项目命令即可 - 看每个包都占了多少可以使用
webpack-bundle-analyzer,命令:npm install webpack-bundle-analyzer打包构建后自动弹出
//在vue.config.js中设置
module.exports = defineConfig({
...
configureWebpack: config => {...},
devServer: {...},
css: {...},
chainWebpack: (config) => {
config.when(process.env.NODE_ENV === 'production', config => {
config.plugin('webpack-bundle-analyzer').use(
require('webpack-bundle-analyzer').BundleAnalyzerPlugin
)
})
}
})
- 主要修改三个文件
public/ndex.html,vue.config.js,src/main.js(涉及全局引入的时候需要修改)
- public/index.html:主要是引入cdn的script
<!DOCTYPE html>
<html lang="">
<head>
...
<link href="https://cdn.bootcdn.net/ajax/libs/element-plus/2.2.26/index.css" rel="stylesheet">
...
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.13/vue.global.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/element-plus/2.2.28/index.full.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/element-plus-icons-vue/2.0.5/index.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.0/axios.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.0.3/vue-router.global.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vuex/4.0.0/vuex.global.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.4.0/echarts.common.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-i18n/9.2.2/vue-i18n.global.min.js"></script>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id="app">
</div>
</body>
</html>
-
vue.config.js:主要是配置webpack的externals,分离打包第三方资源包,这样打包后这些文件就不会打包到vendor.js 和app.js中,会大大减少打包体积
优点:声明文件被外部引用不用打包,不参与打包流程,由于直接写死在html里,可以使用cdn等加速
//定义需要cdn引入的变量,key是依赖包的名称,value是源码抛出来的全局变量
const objExternals = {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
axios: 'axios',
echarts: 'echarts',
'element-plus': 'ElementPlus',
'vue-i18n': 'VueI18n'
}
module.exports = defineConfig({
...
configureWebpack: config => {
// ⚠️按需引入失效,直接删除?不知道理解的对不对
// config.plugins.push(AutoImport({
// resolvers: [ElementPlusResolver()]
// }))
// config.plugins.push(Components({
// resolvers: [ElementPlusResolver()]
// }))
//配置externals
config.externals = objExternals
},
` })``
- Gzip打包压缩需要后端配合,
- 首先安装
npm i -D compression-webpack-plugin - 在 vue.config.js中加入:
module.exports = defineConfig({
...
configureWebpack: config => {
config.plugins.push(new CompressionPlugin({
test: /.js$|.html$|.css/, // 指定压缩文件
threshold: 10240, // 超过10kb的文件进行压缩
deleteOriginalAssets: false// true // 是否删除原文件
}))
},
})
遇到问题:
- 在打包后发现element-plus还是被打包进了依赖项目,原因:没有删除之前设置的按需引入
- 可能会有的样式问题:cdn引入ElementPlus table显示不正常→cdn引入 不支持自结束标签的写法,要写完整标签