Webpack Best Practice Summary (III)
in Tutorial with 0 comment
Webpack Best Practice Summary (III)
in Tutorial with 0 comment

If you haven't read them yet, you can click to view the last two articles: Webpack Best Practice Summary (I) Webpack Best Practice Summary (II)

Well, this is the third and final chapter. I think this is the most messy one. I can make do with it. I won't let you down

Integrate CSS processing flow

Sometimes, in addition to JavaScript, there is a more important CSS in the front-end project that we need to spend some energy on. This article mainly describes how to integrate the CSS processing flow into the webpack. Because the situation involving CSS Modules is complex, it is not planned to introduce more about CSS Modules yet

What does CSS workflow mean? Good workflow can provide development efficiency and save development costs. 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 further processing. Sass and less let us eat 'grammar sugar' to quickly write CSS. PostCSS can let us no longer care whether each statement takes account of different browsers and different versions

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

Configure preprocessor

Sass is used as the preprocessor here, 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, PostCSS is used 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 pictures or normalize.css const staticSourcePath = path.join(__dirname, 'static'); module.exports = { // ... entry: { //Set the entry file in the order of static resources ->custom.scss ->other scss in the project base: path.resolve(staticSourcePath, 'src/public/custom.scss') }, // ... plugins: [ //Create<link>tags and point src to the final generated CSS file. html webpack plugin is required new ExtractTextPlugin({ filename: '[name]. [contenthash].css', allChunks: true }) ] }

Compress third-party libraries

Take Moment.js and Lodash as examples

Moment.js

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

Among them, 165kb language packs are used for localization. Even if you don't use them, they will be included by default. The following code comes from the 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 will make Moment.js dynamically select the corresponding file to load during the run.

To solve this problem, ContextReplacementPlugin, a plug-in that replaces the context, is used. An example is as follows:

 // webpack.config.js const webpack = require('webpack'); module.exports = { plugins: [ new webpack. ContextReplacementPlugin( //File directory location to be processed /moment[\/\\]locale/, //Regular matching of files to be included /(en|zh-cn)\.js/ ) ] };

Lodash

Lodash It is a convenient JavaScript tool set for developers, and the test version is 4.17.4.

When your project contains lodash, the file you package will increase by at least 75kb, and the extra size includes 316 lodash functions. If you only use a few of them, such as 20, then about 65 kb is redundant. Here are two ways to get rid of these redundant codes:

Method 1:

Remember Webpack best practices (1) Did you mention Tree Shaking? Because of it, we can use this feature to easily reference on demand, as follows:

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

Modify to

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

The code size is compressed from 72kb to 8.27kb

Method 2:

Method 1 is only suitable for playing with a project at the beginning, but not very suitable for playing with a project that has been opened. Unless it is rewritten once, the workload is too heavy. Another reason is that the method name of lodash will easily conflict with the user-defined function name, causing hidden bugs. Method 2 is to solve these two problems by using babel-plugin-lodash

babel-plugin-lodash It is a way to realize lodash through babel import The usage is compiled as a best practice plug-in. The configuration is as follows:

open .babelrc , add the following configuration

 { "plugins": ["lodash"] }

More configuration methods can be viewed file , no more introduction here. More specific optimization effects are as follows:

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

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

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

As in 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 will further delete the code in some lodash methods. for example _.get By default, it supports deep path query. If you do not 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

Compressed code 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

Currently, only webpack v3 and above can support 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 Let static resources support DNS pre resolution and pre loading. The configuration is 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 the 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 is a bit messy and difficult to summarize. It is probably to integrate CSS code processing process into webpack, compress third-party libraries (Moment.js and Lodash), and enable scope hoisting And other useful plug-ins, I wrote an article about basic introduction before: Webpack2 Basic Tutorial

That's about it. More content~

Responses / Cancel Reply