分析工具:webpack-bundle-analyzer
使用范围:对于打包结果进行分析;
使用方法:
下载:
npm install --save-dev webpack-bundle-analyzer;
引入:在vue.config.js文件中,
调整 webpack 配置最简单的方式就是在 vue.config.js
中的 configureWebpack
选项提供一个对象:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { configureWebpack:config=>{ //该配置会通过webpack-merge合并到webpack配置中 if(process.env.NODE_ENV == 'production'){//判断执行环境,只有在生成环境中用到,开发环境中用不到分析工具,文档:https://cli.vuejs.org/zh/guide/webpack.html#%E7%AE%80%E5%8D%95%E7%9A%84%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F return {
devtool: 'none', plugins: [ new BundleAnalyzerPlugin() ] } } }, ... }
通过分析工具可以看出,打包结果分为两部分:node_modules和src,其中前者是引入的公共包,后者是自己写的。
前者分为:
1. mockjs/dist不需要打包进入,
2. vue. vue-router、vuex和axios不无法优化的固定代码:
针对这部分可以采用cdn(content delivery network)方式引入公共的免费资源:
具体步骤:
(1)告诉webpack,不要对vue. vue-router、vuex和axios这些可以从cdn上免费获取的公共资源进行打包;
externals
配置选项提供了「从输出的 bundle 中排除依赖」的方法。
//vue.config.js文件
module.exports = { configureWebpack:config=>{ if(process.env.NODE_ENV == 'production'){ return { devtool: 'none', plugins: [ new BundleAnalyzerPlugin() ], externals:{ vue: 'Vue',//引入cdn上的资源后,将会生成全局变量Vue vuex: 'Vuex', 'vue-router': 'VueRouter', axios: 'axios' } } } },
(2).在public目录下的index.html中,手动从cdn引入这几项,(注意用到了模板语法,这是html-webpack-plugin插件的语法)
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> </head> <body> <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> <!-- ref cdn 开发环境不需要,生成环境需要,这是html-webpack-plugin的模板语法,当环境是生成环境时候,不需要引入cdn --> <% if( NODE_ENV === 'production' ){ %> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.13/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script> <% } %> </body> </html>
此时,打包的文件没有了这四项公共的模块。
(3)由于用cdn方式引入,模块化引入的方式是不能写的,比如Vue.use(Vuex),Vue.use(VueRouter)
import Vue from 'vue'; import VueRouter from 'vue-router'; import routes from './routes'; import setTitle from '@/utils/setSiteTitle';
//在production的条件下,由于vue.config.js中用了external, //把VueRouter暴露到全局,所以会存在,就不能用这种方式加载VueRouter了 if(!VueRouter){ Vue.use(VueRouter); } const router = new VueRouter({ mode: 'history', // base: process.env.BASE_URL, routes, })
core-js是浏览器兼容的代码,
这个corejs是按需引入的,所以不需要我们在做处理。
如果兼容的是新版本浏览器,可以不需要考虑兼容性,直接把babel.config.js里的preset值去掉就可以了。
用npm run modern modern命令,打包出两种不同兼容性的代码;
这篇博客挺好的:https://blog.csdn.net/weixin_34321753/article/details/89701992
Vue CLI 构建两个版本的 js 包:一个面向支持现代浏览器的原生 ES2015+ 包,以及一个针对其他旧浏览器的包。
但最酷的部分是没有特殊的部署要求。生成的HTML文件中自动适配。 这个方式采用了Phillip Walton 文章中讨论的技术方案:
-
在支持原生 ES2015+ 的浏览器中,js会通过
<script type="module">
加载,并且可以使用<link rel="modulepreload">
预加载。 -
在不支持的浏览器中使用
<script nomodule>
来加载编译版本,并且这会被支持ES模块的浏览器所忽略。
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1"> <link href="/css/chunk-249149b2.bc811261.css" rel="prefetch"> //perfeth和preload都是懒加载,但preload的优先级要高 <link href="/css/chunk-3de993f6.c13ff11f.css" rel="prefetch"> <link href="/css/chunk-5d499e19.25e41ee9.css" rel="prefetch"> <link href="/css/chunk-61542f76.899679a2.css" rel="prefetch"> <link href="/css/chunk-71cb7586.eb46b54a.css" rel="prefetch"> <link href="/js/chunk-249149b2.9522a5e5.js" rel="prefetch"> <link href="/js/chunk-3de993f6.e812e81e.js" rel="prefetch"> <link href="/js/chunk-5d499e19.b2738f79.js" rel="prefetch"> <link href="/js/chunk-61542f76.62cfd7c4.js" rel="prefetch"> <link href="/js/chunk-71cb7586.8a1a4a95.js" rel="prefetch"> <link href="/css/app.ac0c3dd2.css" rel="preload" as="style"> <link href="/js/app.cedc65b7.js" rel="modulepreload" as="script"> <link href="/js/chunk-vendors.f5d25c35.js" rel="modulepreload" as="script"> <link href="/css/app.ac0c3dd2.css" rel="stylesheet"> </head> <body><noscript><strong>We're sorry but my-site doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript> <div id="app"></div> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.13/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.2.0/vue-router.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script> <script type="module" src="/js/chunk-vendors.f5d25c35.js"></script> //非现代浏览器会忽略type=module的引入 <script type="module" src="/js/app.cedc65b7.js"></script> <script>!function () { var e = document, t = e.createElement("script"); if (!("noModule" in t) && "onbeforeload" in t) { var n = !1; e.addEventListener("beforeload", function (e) { if (e.target === t) n = !0; else if (!e.target.hasAttribute("nomodule") || !n) return; e.preventDefault() }, !0), t.type = "module", t.src = ".", e.head.appendChild(t), t.remove() } }();</script> <script src="/js/chunk-vendors-legacy.f5d25c35.js" nomodule></script> //现代浏览器会忽略nomodule属性的标签 <script src="/js/app-legacy.6a3f1c73.js" nomodule></script> </body> </html>
对自己写的代码的优化
路由懒加载:函数返回promise,结果是组件。打包后进行了分包
import Home from '@/views/Home/index.vue' const routes = [ { path: '/', name: 'Home', component: Home, meta:{ subTitle: '主页' } }, { path: '/about', name: 'About', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import( '@/views/About/'), meta:{ subTitle: '关于' } },
刚打开网站的白屏处理:
处理方法有多种:
1.在#app元素中插入一张加载动画,
如果vue没加载出来,#app中的内容不会消失,一旦new Vue()执行,因为有render函数介入,#app的内容会render的内容被覆盖。
注意:该动画图片的路径必须是public目录下,因为该目录下,会经过copy-webpack-plugin的插件,原封不动的复制到dist目录。而不是和assets目录下的图片,会经过loader解析,成为新文件。
静态文件分为static和asset文件,,static是纯静态文件,而assets是经过loader处理的文件,在vue-cli中,static文件放在public目录中
2.在加载中添加进度条
在vue-cli中,可以直接在代码中判断当前的环境是开发还是生产环境。用