Laravel框架中缩小webpack打包vue js的体积

转载,原文: Laravel框架中缩小Vue应用的体积 https://www.codercto.com/a/12720.html

laravel中 webpack打包生成的app.js居然有3M,生成的production版也有1.4M,放到服务器上,首页打开要十几秒(1M带宽)。于是探究起如何缩小应用体积。

定位导致应用体积大的原因

这里使用 webpack-bundle-analyzer ,该插件可以将内容束显示为很直观的树状图,让你明白构建包中真正引入的内容。借助这个插件可以了解应用有哪些模块组成,找到不合时宜的存在,然后进行优化。

  1. 安装: npm install --save-dev webpack-bundle-analyzer
  2. 修改webpack.mix.js,注意Laravel自带的 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 来展示结果

解决办法

从上面的这张图可以分析出导致应用体积变大的原因就是在于引用很多第三方库,这些库会被webpack一起打包到应用内,所以减小应用体积的最有效方法就是将这些库分离出去,别将它们与我们自己写的应用代码打包到一起。大部分有名的第三方库在公共CDN都有存放,如 bootcss , unpkg 等,速度飞快,可以直接引用。

webpack的选项有一个 externals ,可以指定哪些包不参与打包,即忽略掉相应 import XXX from package ,而代码中依旧可以通过CMD、AMD或window/global全局的方式访问。

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文件中加入外链

<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/[email protected]/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了,这大小已经不成问题了

需要注意的是:这样优化之后 app.js中不能使用use(注释掉所有use,例如: Vue.use(ElementUI) ),否则会编译不通过报错

至此,可以说已经优化完毕,后面的进一步优化可以选择跳过,想要继续优化的可以接着继续操作

进一步优化

这里将第三方库完全改为外链,在生成环境内是没问题,但我们在开发时,并不希望每次都是从网络获取第三方库,网络加载始终不会有本地加载来的快,本地加载并不需要考虑大小问题。

我们可以通过使用环境变量来控制要不要使用外链。

在.env中添加一个变量 MIX_EXTERNAL=true (注意:如果要在App应用里使用这个变量,这里必须是以 MIX_ 开头,参考Mix 环境变量)

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/[email protected]/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 里修改一下变量,即可在两种打包方式间切换,可以愉快地继续开发了。

猜你喜欢

转载自blog.csdn.net/a314753967/article/details/82996135