应用场景:
随着项目越来越大,引用的第三方依赖越来越多,会导致项目打包速度越来越慢,发版非常耗时。
解决思路:
对于第三方库我们只是引入到项目里来,一般不会去做修改,因此可以把第三方依赖预打包,只有有变化的时候打包一次
step1: 初始化项目(这里不做详细描述)

step2: 看一下main.js中引入第三方依赖

import Vue from 'vue'
import App from './App'
import router from './router'
import iView from 'iview'
import VueBus from 'vue-bus'
import lodash from 'lodash'
import vuex from 'vuex'
import ElementUI from 'element-ui'
import axios from 'axios'
import vueRouter from 'vue-router'

Vue.config.productionTip = false

Vue.use(iView)
Vue.use(ElementUI)
Vue.use(VueBus)
Vue.use(lodash)
Vue.use(vuex)
Vue.use(axios)
Vue.use(vueRouter)

step3: 预打包依赖模块
在build文件夹下创建一个webpack.dll.config.js

var path = require("path");
var webpack = require("webpack");

module.exports = {
  // 你想要打包的模块的数组
  entry: {
    vendor: ['vue/dist/vue.esm.js', 'lodash', 'vuex', 'axios', 'vue-router', 'vue-resource', 'vue-bus','moment']
  },
  output: {
    path: path.join(__dirname, '../static/js'), // 打包后文件输出的位置
    filename: '[name].dll.js',
    library: '[name]_library'
    // vendor.dll.js中暴露出的全局变量名。
    // 主要是给DllPlugin中的name使用,
    // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '.', '[name]-manifest.json'),
      name: '[name]_library',
      context: __dirname
    }),
    // 压缩打包的文件,与该文章主线无关
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};

重点:这里引入的Dllplugin插件,而 DLLPlugin 则是能把第三方代码完全分离开,即每次只打包项目自身的代码。该插件将生成一个manifest.json文件,该文件供webpack.config.js(webpack.base.conf.js)中加入的DllReferencePlugin使用,使我们所编写的源文件能正确地访问到我们所需要的静态资源(运行时依赖包)。

path:manifest.json生成的文件夹及名字,该项目让它生成在了根目录下。
name:和output. library保持一致即可。
context:选填,manifest文件中请求的上下文,默认为该webpack文件上下文。

以指定webpack文件执行webpack打包
webpack --config ./webpack.dll.config.js

我们把这句话加入到package.json里

"scripts": {
    "dev": "node build/dev-server.js",
    "build": "node -max_old_space_size=4096  build/build.js",
    "build:dll": "webpack --config build/webpack.dll.conf.js"
  },

打包:执行 npm run build:dll命令

$ npm run build:dll

> zhsq-data@1.0.0 build:dll H:\zhsq_web
> webpack --config build/webpack.dll.conf.js

Hash: ab41b3c5a567da44386e
Version: webpack 2.7.0
Time: 5329ms
        Asset    Size  Chunks                    Chunk Names
vendor.dll.js  511 kB       0  [emitted]  [big]  vendor
   [0] ./~/moment/moment.js 174 kB {0} [built]
   [2] ./~/process/browser.js 5.42 kB {0} [built]
   [4] (webpack)/buildin/global.js 509 bytes {0} [built]
 [142] (webpack)/buildin/module.js 517 bytes {0} [built]
 [143] ./~/axios/index.js 40 bytes {0} [built]
 [144] ./~/lodash/lodash.js 540 kB {0} [built]
 [145] ./~/vue-bus/dist/vue-bus.esm.js 837 bytes {0} [built]
 [146] ./~/vue-resource/dist/vue-resource.es2015.js 35.9 kB {0} [built]
 [147] ./~/vue-router/dist/vue-router.esm.js 65.6 kB {0} [built]
 [148] ./~/vue/dist/vue.esm.js 282 kB {0} [built]
 [149] ./~/vuex/dist/vuex.esm.js 26.1 kB {0} [built]
 [150] ./~/axios/lib/axios.js 1.37 kB {0} [built]
 [168] ./~/moment/locale ^\.\/.*$ 3.21 kB {0} [optional] [built]
 [170] ./~/timers-browserify/main.js 1.36 kB {0} [built]
 [171] dll vendor 12 bytes {0} [built]
    + 158 hidden modules

看到这个就是第三方依赖已经打包好了,我们的目录结构中多生成了static目录,打包好的dll文件(js/vendor.dll.js)就放在该目录下,除此之外build目录中还生成了vendor-manifest.json。

可以看一下vendor-manifest.json文件,每一个公共库中的js文件,都会有一个对应的资源ID。

vendor.dll.js,一般是依赖库, 这个文件会暴露给全局一个类似require功能的函数,这个全局函数的名字是可以配置的, 比如,可以为 vendorRequire();

现在我们已经不再需要将使用的那些包同源文件一起打包了,但是这也需要在源文件的webpack中配置DllReferencePlugin使用vendor-manifest.json来引用这个dll。

step4:引入DllReferencePlugin 插件

让在打包业务组件的时候自动引入第三方依赖打包好的资源,根据vendor-manifest.json中对应的资源id。

DllReferencePlugin 是在打包过程中使用的,在打包业务代码时,每遇到一个在manifest.json中出现的文件,就可以利用上述 vendor.dll.js 暴露的全局函数进行相应处理,而不会把这个文件打包进来。

这一步我们只需要改写vue-cli为我们生成好的webpack.config.js((webpack.base.conf.js))即可:

var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
var webpack = require('webpack')
var AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  entry: {
    app: './src/main.js'
  },
  externals: {
    'AMap': 'AMap'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src')
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'),resolve('node_modules/element-ui/src/mixins/emitter.js'),resolve('node_modules/element-ui/packages/col/src/col.js'),resolve('node_modules/element-ui/packages/row/src/row.js'),resolve('/config/axios.js')]
      },
      {
        test: /\.scss$/,
        loaders: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require('./vendor-manifest.json')
    })
  ]
}

新增了这段代码:

new webpack.DllReferencePlugin({
  context: __dirname,
  manifest: require('./vendor-manifest.json')
})

step5:在根目录的index.html里引入所生成的dll库
手动加入:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
  </head>
  <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.11&key=9c9f2211a2e37eecf6ecba9c2e36086b"></script>
  <body id="body"    >
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="./static/js/vendor.dll.js"></script>
  </body>
</html>

自动添加:用到add-asset-html-webpack-plugin插件

npm add-asset-html-webpack-plugin --save

打开webpack.config.js((webpack.base.conf.js))文件
在plugins中加入如下代码:

new AddAssetHtmlWebpackPlugin({
  filepath: resolve('static/js/vendor.dll.js'),
  includeSourcemap: false,
  hash: true
}),

到这里优化就结束了,我们打包下看看优化后的速度,我们项目打包已经从原来的将近10分钟,变成了不到2分钟
终于不用听后端吐槽前端发版慢啦!

注意:用到的webpack插件版本号都不能高于安装的webpack的版本号,否则会报错
安装特点版本号的命令格式:举个例子
npm install --save add-asset-html-webpack-plugin@2.1.3

Logo

前往低代码交流专区

更多推荐