This article focuses on two plug-ins: the DllPlugin and the DllReferencePlugin, the latter being used in conjunction with the former.

Making address:dll-test

Introduction:

The package outputs a class DLL package (the DLL package is derived from the Windows dynamic link library), which is not executed by itself and is mainly provided to us as a reference to the business code. (For example, there is a tool method for time formatting in the DLL. The method itself is not executed, but when we need to perform time formatting in our business, we will reference this method to perform time formatting in our business.)

In short:

Package the static resource files (run dependency packages) separately from the source file, using DllPlugin to package the static resource, and then using DllReferencePlugin to make the source file reference the resource file.

Function:

When we introduce multiple large packages in a project, the packages themselves don’t run and we don’t change the package code, but when we change the business code, the packages are repackaged. This is a huge waste of time, so we need to use this tool to pre-package the static resources in advance, and then modify the source file and then package these static resources files will not be packaged.

Let’s take the simplest vuE-CLI generated project as an example:

Step 1: Basic installation

Vue init webpack-simple dL-test CD dL-test ## Install NPM install vue-cli -g ## Install vuex vue-router axios lodash element-ui-s NPM install vuex vue-router axios lodash element-ui-sCopy the code

Directory structure:







Step 2: Use dependency and package tests

We go to main.js and import the static resources we installed. The result is:

import Vue from 'vue'
import App from './App.vue'
import _ from 'lodash'
import vuex from 'vuex'
import ElementUI from 'element-ui'
import axios from 'axios'
import vueRouter from 'vue-router'

new Vue({
  el: '#app',
  render: h => h(App)
})
Copy the code

To see which modules we have packed, let’s go to package.json and change scripts:

  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
  },
Copy the code

“Build “: “cross-env NODE_ENV=production webpack –progress”

## Build package NPM run buildCopy the code









Time: 13769 ms






That’s why we introduced the dllPlugin!

Step 3: Pre-package the dependency modules

We know that the vue or Vuex that we just introduced, we just use them, we don’t change their source code, they don’t work, so we can just break them up and pack them in advance. So how do you pack them in advance? Create a webPack configuration file (webpack.dll.config.js) in this directory. Since this file is a Webpack configuration file, it must have the same format as a normal Webpack:

var path = require("path"); var webpack = require("webpack"); Module. exports = {// Array of modules you want to package: {vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'element-ui'] }, output: { path: Path.join (__dirname, './static/js'), // Output location of the file filename: '[name].dll. The global variable name exposed in '[name]_library' // vendor.dll.js. DllPlugin (' name: '[name]_library', 'webpack.dllplugin'); }, plugins: [ new webpack.DllPlugin({ path: path.join(__dirname, '.', '[name]-manifest.json'), name: '[name] _library, context: __dirname}), / / compression package files, has nothing to do with the article main new webpack. Optimize. UglifyJsPlugin ({compress: { warnings: false } }) ] };Copy the code

Key points: The Dllplugin plugin introduced here generates a manifest.json file that is used by the DllReferencePlugin added to webpack.config.js. Enable the source files we write to properly access the static resources (runtime dependencies) we need.

  • Json and the name of the folder that was generated in the root directory.
  • Name = output. library
  • Context: Optional, the requested context in the manifest file, default to the webpack file context. (!!!!!! One of the potholes I have been unsuccessful in learning this plugin!! This context must be the same as the context pointed to by the DllReferencePlugin in webpack.config.js! After writing the Webpack configuration, we can pre-pack the resource files!!
Package webpack -- config. /webpack.dll.config.js to execute webpack with specified webpack fileCopy the code

Yi?? If this is a bit hard to remember, let’s add package.json.

  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
    "build": "cross-env NODE_ENV=production webpack --progress",
    "dll": "webpack --config ./webpack.dll.config.js"
  },
Copy the code

Packaging:




















The static directory (js/vendor.dll. Js) is stored in this directory. In addition, vendor-manifest.json is also generated in the root directory.


Step 4: Package the source files

For this step, we just need to rewrite the webpack.config.js generated by vue-CLI:

var path = require('path') var webpack = require('webpack') module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', filename: 'build.js' }, module: { // ... Resolve: {alias: {'vue$': 'vue/dist/vue.esm.js'}}, devServer: {historyApiFallback: true, noInfo: true }, performance: { hints: false }, devtool: '#eval-source-map', plugins: [ new webpack.DllReferencePlugin({ context: __dirname, manifest: require('./vendor-manifest.json') }) ] } if (process.env.NODE_ENV === 'production') { module.exports.devtool = '#source-map' // http://vue-loader.vuejs.org/en/workflow/production.html module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }) ]) }Copy the code

In this file, the plugins are added:

plugins: [
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require('./vendor-manifest.json')
    })
  ]
Copy the code
  • Context: this is the same as the context in the Dllplugin that points to the root directory.
  • Manifest: The manifest generated by importing the Dllplugin.

Did you think it was over? Not really. We need to manually import the generated DLL libraries in the root directory index. HTML.

<! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>dll-test</title> </head> <body> <div id="app"></div>  <script src="./static/js/vendor.dll.js"></script> <script src="/dist/build.js"></script> </body> </html>Copy the code

Here is also very exquisite, is one of the reasons I failed before!! I was just going to<script src="./static/js/vendor.dll.js"></script>Write to the<script src="/dist/build.js"></script>The back, resulting in an error! We have to import packages in order to use build.js properly. So vendor.dll.js must be introduced before build.js.

The exciting moment has arrived!! We just need NPM run dev!









!!!!!!!!! Time: 3528ms


 [2] ./~/vue/dist/vue.esm.js 268 kB {0} [built]
Copy the code

Notice this line, vue still seems to be packaged with the source file. After a bit of searching, the problem is found here: webpack.config.js:

  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
Copy the code

If you don’t know much about it, you can check out the Resolve Chinese document

This means that the import Vue from ‘Vue’ in main.js is actually a reference to ‘Vue /dist/vue.esm.js’, and webpack.dll.config.js does not know that Vue refers to’ Vue /dist/vue.esm.js’. So we need to modify the webpack.dll.config.js configuration: will

  entry: {
    vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'element-ui']
  },
Copy the code

Instead of

  entry: {
    vendor: ['vue/dist/vue.esm.js', 'lodash', 'vuex', 'axios', 'vue-router', 'element-ui']
  },
Copy the code

Since we have modified webpack.dll.config.js, we need to repackage:

## Repackage the source file NPM run buildCopy the code

Final result:









Time: 1426 ms

This is the end of the optimization, but there’s a little bit of trouble, because every time we go live, we have to create a new folder, copy and paste in index.html, and paste in dist, and then we have to paste in static, and we don’t want that.

Extract the entire folder

Start by installing a few plug-ins:

npm install html-webpack-plugin copy-webpack-plugin clean-webpack-plugin --save-dev
Copy the code

Then we modify the webpack.config.js configuration:

var path = require('path') var webpack = require('webpack') var HtmlWebpackPlugin = require('html-webpack-plugin') var CopyWebpackPlugin = require('copy-webpack-plugin') var CleanWebpackPlugin = require('clean-webpack-plugin') module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/', filename: 'build.[hash].js' }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { } // other vue-loader options go here } }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.(png|jpg|gif|svg)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]' } } ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' } }, devServer: { historyApiFallback: true, noInfo: true, contentBase: path.join(__dirname, 'dist') }, performance: { hints: false }, devtool: '#eval-source-map', plugins: [ new webpack.DllReferencePlugin({ context: __dirname, manifest: require('./vendor-manifest.json') }), new HtmlWebpackPlugin({ inject: true, template: './index.html', filename: 'index.html' }), new CopyWebpackPlugin([ { from: 'static', to: 'static' } ]), new CleanWebpackPlugin(['dist']) ] } if (process.env.NODE_ENV === 'production') { module.exports.devtool = '#source-map'  // http://vue-loader.vuejs.org/en/workflow/production.html module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }) ]) }Copy the code
A difference:
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/',
    filename: 'build.[hash].js'
  },
Copy the code
  • Added hash value to clear browser cache
  • publicPath: '/': Because index.html needs to be packaged in the dist directory, so'build.[hash].js'The reference path of the/dist/into/
Difference between the two:

Three plugins were added to the plugins (do not add them to the if, otherwise the development environment will fail) :

    new HtmlWebpackPlugin({
      inject: true,
      template: './index.html'
    }),
    new CopyWebpackPlugin([
      {from: 'static', to:'static'}
    ]),
    new CleanWebpackPlugin(['dist'])
Copy the code
  • HTML – webpack – the plugin: We want the index.html to be generated in the dist directory, so we refer to the HTml-webpack-plugin, which packages the generated index.html in the output folder by default. Since the index.html needs to reference the packaged static DLL, And vue needs to be mounted on the root component div#app, so we need to introduce a template. The template is in the root directory index.html:
    <! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>dll-test</title> </head> <body> <div id="app"></div>  <script src="./static/js/vendor.dll.js"></script> </body> </html>Copy the code
    • Inject :true: Inject packed JS files at the bottom of the HTML body to ensure script loading sequence.
  • Copy-webpack-plugin: Since we are importing the DLL from static/js/ in dist, we use this plugin to copy the packed static folder to dist.
  • Clean-webpack-plugin: Clean up the dist directory before packaging
Difference between the three:
  devServer: {
    historyApiFallback: true,
    noInfo: true,
    contentBase: path.join(__dirname, 'dist')
  },
Copy the code

ContentBase: path.join(__dirname, ‘dist’), this is to provide the directory for the index. HTML in dev to dist, consistent with the file access path in production.

Finally:

NPM Run Dev can be happily developed, and NPM Run Build can pack up the dist directory and go live as fast as possible. !!!!!!!!!

References:

How to make webpack build 10 times faster, DllPlugin usage LIST OF build performance