(3) webpack best practices

in Tutorials with 3 comments

If you haven't seen it yet, you can click to see the last two articles: Webpack best practices summary (1) Webpack best practices summary (2)

This is the third one. I'm not disappointed

Integrating CSS processing flow

Sometimes, in addition to JavaScript in front-end projects, there is a more important CSS that we need to put our energy into. This paper is mainly about how to integrate the CSS module into the CSS stream

What is CSS workflow? Good workflow can provide development efficiency and save development cost. Here is a common code processing process in CSS workflow: normal CSS business logic development process needs to go through CSS preprocessor (such as sass or less), and then go through post processor (such as postcss) for deep processing. Sass and less let us eat the 'syntax sugar' to quickly write CSS. Post CSS can let us no longer care whether each statement takes into account different and different versions of the browser

The implementation of integrating CSS processing flow on webpack is as follows:

Configure preprocessor

Here, sass is used as the preprocessor, as follows:

 // webpack.config.js
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  module: {
    rules: [
      // ...
      {
        test: /\.scss$/,
        exclude: /node_ modules/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: [
            { loader: 'css-loader', options: { minimize: true } },
            'postcss-loader',
            'sass-loader'
          ]
        })
      }
    ]
  }
}

Configure post processor

Here, we use postcss as the post processor, as follows:

 // webpack.config.js
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');

module.exports = {
  plugins: [
    new webpack.LoaderOptionsPlugin({
      options: {
        postcss: [
          autoprefixer({
            browsers: [
              'last 3 version',
              'ie >= 10'
            ]
          })
         ],
        context: staticSourcePath
      }
    })
  ]
}

Set up outreach

 //Webpack. Config. JS "const extracttextplugin = require ('extract text webpack plugin '); 
 / / store static resources such as images or normalize.css 
 const staticsourcepath = path. Join (__ Dirname,'static ');, module.exports = {(/ / /..., entry: {
 / / sets the entry file, and the sequence is static resources - > custom.scss - > other SCSS in the project, base: Base: path.resolve (static sourcepath,' Src / public / custom / custom.scss')}, 
 / /..., plugins: [(/ / create a < link > tag, and point SRC to the final generated CSS file, which requires html-webback-plug-in SS, other SCSS in the project, base base: Path: path, resolve (static sourcepath, 'Src / public / custom / custom. SCSS'), and, / / /..., plugins: [(/ / creates a < link > tag, and points SRC points SRC to the final generated CSS file, and requires HTML webback-plugin html-webpack-plugin he  new ExtractTextPlugin({
      filename: '[name].[contenthash].css',
      allChunks: true
    })
  ]
}

Compressing third party libraries

Take moment.js and lodash for example

Moment.js

Moment. JS (v2.18.1) is a JavaScript library for dates. By default, only you install it into your project. Even if compressed, it will occupy 217kb. Relative to the Statistics Compared with the average size of 446kb of JavaScript, this is really too big. However, webpack can remove the useless code in moment. JS.

Of these, 165kb are language packs for localization, which are included by default even if you don't use them. The following code is from moment's gitihub

 // moment/src/lib/locale/locales.js
function loadLocale(name) {
    var oldLocale = null;
    // TODO: Find a better way to register and load all the locales in Node
    if (!locales[name] && (typeof module !== 'undefined') &&
            module && module.exports) {
        try {
            oldLocale = globalLocale._ abbr;
            require('./locale/' + name);
            // because defineLocale currently also sets the global locale, we
            // want to undo that for lazy loaded locales
            getSetGlobalLocale(oldLocale);
        } catch (e) { }
    }
    return locales[name];
}

The above code causes moment. JS to dynamically select the appropriate file to load during runtime.

To solve this problem, we need to use contextreplacementplugin, a plug-in to replace the context. Examples are as follows:

 //It's an area that is expected to be used as a part of the world's most popular and well-received (as well as) in the region of the region, where it's expected to be a part of the world's most popular (in-demand) in the region of the region, which is expected to be a part of the world's most popular (in-demand) in the region, it's an area that's expected to be used in the region, and it's an area that's expected to be used in the region, as well as in the region that's expected to be used in the region, as well as in the region, it's in the region of the region, as well as in the region, in the region of the region, in the region of the region, in the region of the most of the most of the most of the most of the most of the most of the most of it's a good idea;

Lodash

Lodash Is a user-friendly collection of JavaScript tools, the test version is 4.17.4.

When your project contains lodash, the file you package should be increased by at least 75KB, and the extra size contains 316 lodash functions. If you use only a few, for example, 65 KB. Here are two ways to get rid of this excess Code:

Method 1

Remember Webpack best practices (1) Did you mention tree shaking? Because of this feature, we can easily use this feature to make on-demand references, as follows:

 import _  from 'lodash';
_ .get();

Revised as

 import get from 'lodash/get';
get();

The code size is compressed from 72kb to 8.27kb

Method 2

In addition, it is not easy to use a method to hide the name of a project when the workload of the method is too large. Method 2 is to solve these two problems, that is to use babel-plugin-lodash

babel-plugin-lodash It's going to be implemented through the dalobesh import The usage is compiled as a best practice plug-in, and the configuration is as follows:

open .babelrc , add the following configuration

 {
  "plugins": ["lodash"]
}

More configuration methods can be viewed file I don't want to talk about it too much here. More specific optimization results are as follows:

 import _  from 'lodash';
_ .get({ a: { b: 5 } }, 'a.b');

The above code is not used babel-plugin-lodash After using, it will be recompiled as follows:

 import _ get from 'lodash/get';
_ get({ a: { b: 5 } }, 'a.b');

As with method 1, the code size is compressed from 72kb to 8.27kb

Of course, if you want to further compress the code, you can try lodash-webpack-plugin With it, it will further delete some code in lodash's methods. for example _ .get Deep path query is supported by default. If you don't need to support deep path query, you can open this plug-in, and this method will be removed

Use only babel-plugin-lodash

 import _  from 'lodash';
_ .get({ a: { b: 5 } }, 'a.b');
// → returns 5

use babel-plugin-lodash and lodash-webpack-plugin after

 import _ get from 'lodash/get';
_ get({ a: { b: 5 } }, 'a.b');
// → returns undefined

Code size compressed from 72kb to 772b

Enable scope hosting

scope hoisting For webpack, it is to flatten the previous module reference chain into one without affecting the existing code. Better understanding scope hoisting Recommended reading: here

At present, only webpack V3 and above are supported scope hoisting To enable it, you need to configure it manually, as follows:

 // webpack.config.js
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.optimize.ModuleConcatenationPlugin()
  ]
};

Other useful plug-ins

preload-webpack-plugin Pre load and pre configure DNS resources as follows:

 // webpack.config.js
const PreloadWebpackPlugin = require('preload-webpack-plugin');
module.exports = {
  // ...
  plugins: [
    new PreloadWebpackPlugin({
      rel: 'preload',
      as: 'script',
      include: 'all',
      fileBlacklist: [/\.(css|map)$/, /base?.+/]
    })
  ]
}

script-ext-html-webpack-plugin Let JS load mode support async or defer. The configuration is as follows:

 // webpack.config.js
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
module.exports = {
  // ...
  plugins: [
    new ScriptExtHtmlWebpackPlugin({
      defaultAttribute: 'defer'
    })
  ]
}

summary

It's a bit messy, and it's not easy to summarize. It's probably to integrate the CSS code processing process into webpack, compress the third-party libraries (moment. JS and lodash), and enable it scope hoisting And other easy-to-use plug-ins, about the basic introduction, I wrote a previous article: Basic course of webpack 2

So, there are more contents~

Responses
  1. Hello

    How to widen it, www.baidu.com

    Reply
  2. Very good!!!!

    Reply
  3. Learning! The writing is in place!

    Reply