这两天写一个很小的Laravel+Vue的先后端分离应用,前端的代码文件并很少,但webpack打包生成的app.js竟然有3M,生成的production版也有1.4M,放到本身的服务器上,那速度彻底没法忍受。因而探究起如何缩小应用体积。css
这里使用webpack-bundle-analyzer,该插件能够将内容束显示为很直观的树状图,让你明白构建包中真正引入的内容。借助这个插件能够了解应用有哪些模块组成,找到不合时宜的存在,而后进行优化。前端
npm install --save-dev webpack-bundle-analyzer
webpack-mix
的配置方式与日常的webpack配置略有不一样const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
mix.webpackConfig({
plugins: [
new BundleAnalyzerPlugin(),
],
}).js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
复制代码
修改完以后像日常同样使用npm run dev
或npm run production
打包应用,打包完成后,会自动打开http://127.0.0.1:8888
来展现结果。 vue
从上面的这张图能够分析出致使应用体积变大的缘由就是在于引用不少第三方库,这些库会被webpack一块儿打包到应用内,因此减少应用体积的最有效方法就是将这些库分离出去,别将它们与咱们本身写的应用代码打包到一块儿。大部分有名的第三方库在公共CDN都有存放,如bootcss
, unpkg
等,速度飞快,能够直接引用。node
webpack的选项有一个externals
,能够指定哪些包不参与打包,即忽略掉相应import XXX from package
,而代码中依旧能够经过CMD、AMD或window/global全局的方式访问。webpack
mix.webpackConfig({
plugins: [
new BundleAnalyzerPlugin(),
],
externals: {
'element-ui': 'Element',
'axios': 'axios',
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'vue-chartjs': 'VueChartJs',
'lodash': '_',
}
}).js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.styles(['node_modules/element-ui/lib/theme-chalk/index.css'], 'public/css/element-ui.css');
复制代码
在blade文件中加入外链ios
<head>
...
<script src="//cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
<script src="//cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/element-ui/2.0.11/index.js"></script>
<script src="//cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
<script src="//cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
<script src="//unpkg.com/vue-chartjs@2.8.7/dist/vue-chartjs.full.min.js"></script>
<link href="https://cdn.bootcss.com/element-ui/2.0.11/theme-chalk/index.css" rel="stylesheet">
...
</head>
复制代码
而后从新打包应用,最后生成的应用只有几十K了,这大小已经不成问题了laravel
这里将第三方库彻底改成外链,在生成环境内是没问题,但咱们在开发时,并不但愿每次都是从网络获取第三方库,网络加载始终不会有本地加载来的快,本地加载并不须要考虑大小问题。web
咱们能够经过使用环境变量来控制要不要使用外链。vue-router
在.env中添加一个变量MIX_EXTERNAL=true
(注意:若是要在App应用里使用这个变量,这里必须是以 MIX_
开头,参考 Mix 环境变量)vuex
Laravel自带的webpack-mix默认不加载.env
文件,但已经带有dotenv
包,加载便可。
最后的webpack.mix.js
文件以下
let mix = require('laravel-mix');
require('dotenv').config();
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
let externals = undefined;
if (process.env.MIX_EXTERNAL === 'true') {
externals = {
'element-ui': 'Element',
'axios': 'axios',
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'vue-chartjs': 'VueChartJs',
'lodash': '_',
};
}
mix.webpackConfig({
plugins: [
// new BundleAnalyzerPlugin(),
],
externals,
})
.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css')
.styles(['node_modules/element-ui/lib/theme-chalk/index.css'], 'public/css/element-ui.css');
复制代码
blade文件:
@if (env('MIX_EXTERNAL'))
<script src="//cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
<script src="//cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/element-ui/2.0.11/index.js"></script>
<script src="//cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
<script src="//cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
<script src="//unpkg.com/vue-chartjs@2.8.7/dist/vue-chartjs.full.min.js"></script>
<link href="https://cdn.bootcss.com/element-ui/2.0.11/theme-chalk/index.css" rel="stylesheet">
@else
<link rel="stylesheet" href="css/element-ui.css">
@endif
复制代码
应用内有些代码须要针对外链作区别处理,如ElementUI,若是使用import
方式引入,须要加入Vue.use(ElementUI)
,但若是使用外链时,这句会出错,因此能够加入判断
if (process.env.MIX_EXTERNAL !== 'true') { // **注意是字符串**
Vue.use(Element);
}
复制代码
在app内使用
process.env.MIX_XXXXX
环境变量时,这些变量实际在打包过程当中已经被替换为变量值(就像C里面的宏定义同样),不会在运行求值,也不存在process
对象,上面的if语句在打包后变成if (false) Vue.use(Element)
至此优化完毕,只需在.env
里修改一下变量,便可在两种打包方式间切换,能够愉快地继续开发了。