Progressive configuration of webpack4 single and multiple pages

preface

Use the version of the package

Webpack ->4.3.0 babel-loader -> 8.0.5nPM ->6.4.1 webpack-cli ->3.3.1Copy the code

Each section corresponds to a demo

Build a multi-page configuration

Refer to DEMO12 for the specific code

Create a new multi-page directory

Create a new module file, specifying that each file in the module directory must have an HTML file and a JS file with the same name as the entry file.

Creating variable functions

Create a new method in help.js in the build folder

@param {array} [path address] * @param {array} [path address] * @return: {file name: file address} */ exports. GetEntry =function getEntry(globPath) {
	var entries = {};
	if(typeof(globPath) ! ="object") {globPath = [globPath]} globpath. forEach((itemPath) => {// glob.sync(itemPath).foreach (function(entry) {
				entries[entry.substring(13, entry.lastIndexOf('. '))] = entry; / / 13 representative'./src/module/'
		});
	});
	return entries;
};
Copy the code

Introduce multi-page files

inwebpack.base.jsInside the introduction of multi-page entry files

var entries = help.getEntry(['./src/module/**/*.js']); // Get the js file console.log(entries); /** Print the result {'demo/demo': './src/module/demo/demo.js'.'test/test': './src/module/test/test.js'} * * /Copy the code

Add to entry file

entry:Object.assign({},{app:help.resolve('./app.js')},entries),
Copy the code

inwebpack.base.jsIt introduces multi-page HTML files

function concatHtmlWebpackPlugin() {
  var entriesHtml = help.getEntry(['./src/module/**/*.html']); Console. log(entriesHtml) /** Prints the result {'demo/demo': './src/module/demo/demo.html'.'test/test': './src/module/test/test.html' }
  **/
  var res = [];
  for (var i in entriesHtml) {
    var html = entriesHtml[i];
    var obj = new htmlWebpackPlugin({
      filename: '. ' + html.substring(html.lastIndexOf('/'), template: HTML, // HTML template path inject:true, // What is allowed to be modified by the plugin, including head and body chunks: ['vendors'Minify: {// Compress HTML file removeComments: isPord, // Remove HTML annotations collapseWhitespace: MinifyCSS: isPord // compression inline CSS},}) res.push(obj)}return res
}
Copy the code

Injecting multiple pages

  plugins:[
    
    new htmlWebpackPlugin({
      filename:'index.html',
      template:'./index.html',
      inject:true,
      chunks: ['vendors'.'app'], // Specify to import some entry files minify: {// compress HTML file removeComments: isPord, // remove HTML annotations collapseWhitespace: MinifyCSS: isPord // compression inline CSS},})]. Concat (concatHtmlWebpackPlugin())Copy the code

SplitChunks are configured by default

  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true}}}},Copy the code

Run the command

npm run dev
Copy the code

Multi-page unpacking configuration

Refer to DEMO12 for the specific code

The JS files on each page introduce various packages

src/module/demo/demo.js


import axios from 'axios';
import xlsx from 'xlsx';
import dropzone from 'dropzone';
import lodash from 'lodash';
console.log(lodash);
console.log(dropzone);
console.log(xlsx);
console.log(axios);
var s=document.createElement('div')
s.innerHTML='dome file'
document.getElementById('app').appendChild(s);
Copy the code

Lodash, Dropzone, XLSX, and Axios are introduced.

src/module/test/test.js

import echarts from 'echarts';
import xlsx from 'xlsx';
import dropzone from 'dropzone';
console.log(dropzone);
console.log(xlsx);
console.log(echarts)
var s=document.createElement('div')
s.innerHTML='the test file'
document.getElementById('app').appendChild(s);
Copy the code

Dropzone, XLSX and Echarts are introduced.

app.js

import "regenerator-runtime/runtime";
import React from 'react';
import ReactDOM from 'react-dom';
import About from './src/view/about';
import Inbox from './src/view/inbox';
// import asyncComponent from './src/assets/js/AsyncComponent'
// const Inbox = asyncComponent(() => import( './src/view/inbox'));
// const About = asyncComponent(() => import( './src/view/about'));
import { BrowserRouter as Router, Switch, Redirect, Route, Link, HashRouter ,RouteChildren} from 'react-router-dom'
class App extends React.Component {
  render() {
    return (
      <div className="shopping-list">
      {this.props.children}
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>
      </div>
    );
  }
}

class Home extends React.Component {
  render() {
    return (
      <HashRouter>
        <Switch>
          <App>
            <Route path="/about" component={About} />
            <Route path="/inbox" component={Inbox} />
          </App>
        </Switch>
      </HashRouter>
    )
  }

}

ReactDOM.render(
  <Home />,
  document.getElementById('app'));Copy the code

React and react-dom packages are introduced.

Unpacking analysis

Demo.js and test.js use the same packages dropzone and XLSX. App.js only uses react and react-dom.

SplitChunks are configured by default.

optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          name:'vendors',
          chunks: 'all'.test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true}}}},Copy the code

Direct packaging

npm run build
Copy the code
npm run server
Copy the code

The results of

conclusion

Note The imported packages are packaged into a JS file, and each multi-page is loaded with extra packages. So the default configuration does not work well for multi-page unpacking.

Unpack and optimize the configuration

Modify splitChunks code

optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true, cacheGroups: {reactVendors: {//reactVendors to match react related packet chunks:'all'.test: /(react|react-dom|react-dom-router)/,
          priority: 100,
          name: 'react',}, commonVendors: {// commonVendors to match XLSX and Dropzone packet chunks:'all'.test: /(dropzone|xlsx)/,
          priority: 90,
          name: 'commonMode',
        },
        vendors: {
          name:'vendors',
          chunks: 'all'.test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true}}}},Copy the code

Two matching items, commonVendors and reactVendors, are configured. Let’s see if we can.

npm run build
Copy the code

So the chunks don’t have to import packets so you have to import them.

Different import files introduce different chunks

So the app.js entry file needs to introduce react chunks.

   new htmlWebpackPlugin({
      filename:'index.html',
      template:'./index.html',
      inject:true,
      chunks: ['vendors'.'app'.'react'CollapseWhitespace: isPord, // Delete whitespace and newlines minifyCSS: IsPord // compression inline CSS},})].concat(concatHtmlWebpackPlugin())Copy the code

Multiple pages need to introduce commonMode chunks.

function concatHtmlWebpackPlugin() {
  var entriesHtml = help.getEntry(['./src/module/**/*.html']);
  console.log(entriesHtml)
  var res = [];
  for (var i in entriesHtml) {
    var html = entriesHtml[i];
    var obj = new htmlWebpackPlugin({
      filename: '. ' + html.substring(html.lastIndexOf('/'), template: HTML, // HTML template path inject:true, // What is allowed to be modified by the plugin, including head and body chunks: ['vendors',i,'commonMode'],// I represents the import file key minify: {// compress HTML file removeComments: isPord, // Remove HTML annotations collapseWhitespace: MinifyCSS: isPord // compression inline CSS},}) res.push(obj)}return res
}
Copy the code

After the configuration is complete.