2
头图

1. Background

The current website project uses multiple pages, and development and reconstruction are separated. When developing new pages, because reconstruction development may often add style files or adjust the order of styles, the team adopted the following development model
alt 当前构建流程图
With more and more pages, more style files depend on, and more gulp . The slow speed of packaging and compiling is gradually exposed. The screenshot of the packaging time in this mode is as follows:
alt 当前构建时间
You can see that the gulp task requires about 30s , and the webpack task requires 30s . In addition, the first build takes more than 1 minute, and the second build takes about 8 seconds. Imagine that this scene jumps out of your head every time you build. This is tolerable ? It can be seen that it has reached the point where (ren) must (wu) must (ke) be changed (ren), okay?
alt 图片

So decided to modify the current construction method, divided into the following steps

1. Remove gulp
The modified mode is as shown in the figure below. The green is the new process. Compared with the original process, the gulp package css process is handed over to webpack processing.
alt 修改后流程图
After switching to this mode, the first packaging time is about 20s, and incremental compilation is about 8s

2. webpack build speed optimization

2.1 exclude include optimization

Specify the files that need to be processed and excluded from processing in the matching rules, narrow the scope of search and processing files, ensure that as few files as possible are compiled, and add the corresponding include and exclude configurations for the project. The specific configuration is as follows

rules: [
    {
        test: /\.[jt]s$/,
        include: [path.resolve(process.cwd(), 'src')],
        exclude: [/node_modules/, path.resolve(process.cwd(), 'src/vendor')],
    },
    {
        test: /\.css$/,
        include: RESOURCES.CSS.cwd,
    }
]

After adding the above configuration, the first packaging time is about 16s, and the incremental compilation is about 8s

2.2 thread-loader and esbuild-loader optimization

thread-loader is a multi-process packaging method. The thread-loader behind loader will run in a worker
esbuild by Go developed for packaging compressed ts , js tool is characterized by swift package soon, the official github introduction and webpack , rollup , Parcel compared to tens or even hundreds of times faster, but esbuild not currently support css and no plug-in mechanism, so the time being can not be replaced webpack, but for webpack in loader That esbuild-loader , introducing it to try effect, Vite and Snowpack bottom have adopted esbuild , reference thread-loader official explanation and esbuild-loader official explanation The key configuration is as follows

const cpuNum = require('os').cpus().length;

const tsWorkerPool = {
    workers: 6,
    poolTimeout: Infinity
};

const cssWorkerPool = {
    workers: cpuNum - tsWorkerPool.workers,
    poolTimeout: Infinity
};

threadLoader.warmup(tsWorkerPool, ['esbuild-loader']);
threadLoader.warmup(cssWorkerPool, ['css-loader']);

module: {
    rules: [
        {
            test: /\.[jt]s$/,
            use: [
                {
                    loader: 'thread-loader',
                    options: tsWorkerPool
                },
                {
                    loader: 'esbuild-loader',
                    options: {
                        loader: 'ts',
                        target: 'es2015',
                        tsconfigRaw: require('../tsconfig.json')
                    },
                },
                {
                    loader: path.resolve(__dirname, 'loaders/importcss-loader.js'),
                    options: {
                        include: path.resolve(process.cwd(), 'src/app'),
                    }
                },
            ],
            include: [path.resolve(process.cwd(), 'src')],
            exclude: [/node_modules/, path.resolve(process.cwd(), 'src/vendor')],
        },
        {
            test: /\.css$/,
            use: [
                {
                    loader: MiniCssExtractPlugin.loader,
                },
                {
                    loader: 'thread-loader',
                    options: cssWorkerPool
                },
                {
                    loader: 'css-loader',
                    options: {
                        esModule: false,
                    }
                },
                {
                    loader: 'esbuild-loader',
                    options: {
                        loader: 'css',
                        minify: true
                    }
                }
            ],
            include: RESOURCES.CSS.cwd,
        }
    ],
},

After testing, plus thread-loader the first time about packing 12s , incremental compilation probably 3s , plus esbuild-loader after the first packaged shortened to 8s around, incremental compilation probably 2s
Note: The https://esbuild.github.io/api/#target document mentions that most of the syntax esbuild-loader only supports conversion to es6 , so it is only suitable for use in a development environment, and

2.3 Image compression and removal of redundant css style files

The image compression configuration is as follows

loader: 'image-webpack-loader',
options: {
    // 生产环境启用压缩
    disable: process.env.NODE_ENV === 'production' ? false : true,
    // 压缩 jpg/jpeg 图片
    mozjpeg: {
        progressive: true,
        quality: 80 // 压缩率
    },
    // 压缩 png 图片
    pngquant: {
        quality: [0.65, 0.90],
        speed: 4
    }
}

Remove redundant styles and use the purgecss plug-in, the configuration is as follows, you need to add configuration for special can not be removed

new PurgecssPlugin({
    paths: glob.sync([
        path.resolve(__dirname, '../../server/views/**/*.html'),
        path.resolve(`${PATH.SRC}/**/*.vue`),
    ]),
    safelist: [
        /data-v-.*/, // vue scope样式保留
        /market-message/, // 处理营销通知栏背景颜色由配置决定导致需要剔除样式不确定的特殊处理
        /vip/, // 动态渲染vip等级样式保留
    ]
})

3. Upgrade to webpack5

webpack released last year webpack5 brought a lot of optimization, the main points such as:
1. Persistent cache is turned on by default and cached in memory, while webpack4 needs to use cache-loader and hard-source-webpack-plugin for caching
2, NodeJS the polyfill scripts are removed, while in webpack4 and previous versions, for most Node module automatically adds polyfill script, resulting in the packing volume is large.
3. Better TreeShaking
After the above optimization, I want to further test webpack5 version can bring, upgrade the webpack package and related dependencies to the latest version, remove the incompatible speed-measure-webpack-plugin and the no longer needed hard-source-webpack-plugin plug-ins, and process about 65 files. The packaging time is reduced to 6.5s , and the incremental compilation time is 1.5s . It can be seen that the time has been further shortened.
alt 增量编译
alt 增量编译

4. Hot reload and hot update

Add the following configuration in webpack.dev.js

devServer: {
    contentBase: path.join(PATH.DIST, 'js'),
    inline: true,
    compress: true,
    port: 5000,
    writeToDisk: true,
    host: '0.0.0.0',
    hot: true,
    disableHostCheck: true,
    headers: {
        'Access-Control-Allow-Origin': 'https://www.midasbuy.com',
        'Access-Control-Allow-Headers': '*',
        'Access-Control-Allow-Methods': '*',
        'Access-Control-Allow-Credentials': true,
    },
},

Because we used the whistle agent to cooperate with domain name access during websocket to notify the file when the file was updated. Therefore, we need whistle . The first is to establish a websocket connection, and the second is to use request updated content when in hot update, this is mainly achieved vue heat of the updated components and js hot refresh, css not being realized with the new hot.

https://www.midasbuy.com:5000 http://127.0.0.1:5000/
^https://www.midasbuy.com/oversea_web/static/***hot-update***  http://127.0.0.1:5000/oversea_web/static/$1hot-update$2

Pit: When testing the hot refresh, the file is modified, and the following error is displayed after the page is refreshed

Then manually refresh it again. I didn’t find the reason for a long time. I suspected that it was the whistle agent. Later, I suspected that the notification update command was sent too early. Then I wrote a hack method to delay the sending of the update command. I found that it was OK, but The specific reason has not been found, until I switched to the server terminal, I saw the following print when updating the file
alt 服务端终端打印信息
I understand that our process is client side, the file will be copied to the server folder to provide it to ejs include use. server uses nodemon . When the file is changed, it will copy the file operation and trigger the restart nodemon Causes the browser reload to fail the request, so the solution is to nodemon configuration file, because the real content of the copy is <style link='*****'></style> and <script src='*****'></script> , so it can be completely ignored. When the file changes after ignoring The server will not restart, and the problem is solved.

5. vue devtools locates to the component directory

For vue devtools provided in the browser to select components, you can directly open when you click the compiler and open source components where the code files, reference documentation in webpack.dev.js add the following configuration

const openInEditor = require('launch-editor-middleware');

devServer: {
    ...
    before(app) {
        app.use('/__open-in-editor', openInEditor('code', path.resolve(process.cwd(), 'src')));
    },
},

Add a line of rules in whistle

https://www.midasbuy.com/__open-in-editor http://127.0.0.1:5000/__open-in-editor

As shown in the figure below, when you click on the circled position, the vscode editor will open and locate the corresponding source file code of the component
361618191612_.pic_hd.jpg

6. Summary

In the MacBook Pro Intel Core i7 16G memory 250G hard disk size test environment, the comparison of the compilation time under different schemes and gzip compression results are as follows, in the 65 files, you can see that the compilation time is greatly shortened, and the js is also different. Decrease, but because some pictures are coded base64 css size of the style file has increased.

ProgramFirst compile timeSecond compilation timebuypage.jspropsOrder.jsbuypage.csspropsOrder.css
gulp+webpack460s8s178kb157kb17.58kb24.74kb
webpack56.5s1.5s123kb112kb28kb35kb

timewilltell
68 声望4 粉丝

本人方向为前端,从八月份准备到九月份面试到十月份拿到满意的offer,前前后后大概两个月,期间面试了很多互联网公司,在面试中发现基础占了80%,项目和其他占了20%,现在面试结束了,想系统的把前端常见的面试问...