【专项学习】 —— Webpack5从入门到精通课程学习(五)

这篇主要介绍《webpack优化环境配置(中)》。(demo代码github地址

知识点包括:

  1. 第一种方法
  2. 第二种方法
  3. 第三种方法

 

一、tree shaking

1、复制上一篇的生产环境缓存工程文件。然后重命名。

tree shaking(树摇)去除无用的代码

2、在src文件夹下新建test.js,测试使用该功能,是否会把没有引用的js代码也打包。

test.js代码如下,两个函数都使用export暴露出去。

export function mul(x, y) {
    return x * y;
}
export function count(x, y) {
    return x - y;
}

3、index.js代码,我们只引入test.js中的一个mul函数,那么count函数就没有被用到,那么使用tree shaking后,打包后的文件应该没有count函数,被去掉了。

import '../css/index.css';
// 引入icon-font样式文件
import '../iconfit/iconfont.css';

// 只引入test.js中的一个mul函数
import { mul } from './test';

function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}


console.log(mul(2, 2));

console.log(sum(1, 2, 3, 4));

4、config中需要修改运行环境为production环境,注释说明入代码中所写

const { resolve } = require('path');
const minicssextractplugin = require('mini-css-extract-plugin');
const cssminimizerwebpackplugin = require('css-minimizer-webpack-plugin');
const Htmlwebpackplugin = require('html-webpack-plugin');

// css浏览器兼容性处理,默认是运行在生产环境下,若要运行于开发环境,还需做以下代码
process.env.NODE_ENV = 'production'

// tree shaking:去除无用代码
//前提: 1.必须使用ES6模块化2.开启production环境
//作用:减少代码体积
//在package.json中配置"sideEffects" : false所有代码都没有副作用(都可以进行tree shaking)
//问题:可能会把css/@babel/polyfill (副作用)文件干掉,因为这些文件都是引入了,但没有直接使用
//,所以需要配置为"sideEffects" : ["*.css"]

module.exports = {
    entry: {
        // 把之前的单入口修改为多入口
        // 有几个入口,打包就生成几个built.js
        index: './src/js/index.js',
        test: './src/js/test.js'
    },
    output: {
        // [name]:取entry中的入口文件名进行命名
        filename: 'js/[name].[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [{
            // oneOf 是每一个文件,只匹配到一个loader即可,
            // 不像之前,每个文件都要把下列loader全部匹配一遍
            // 注意不能有两个loader处理同一个类型文件
            oneOf: [
                {
                    // 检测css文件,并打包
                    test: /\.css$/,
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 对css做兼容性处理
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        }
                    ]
                },
                {
                    // 检测less文件,并打包
                    test: /\.less$/,
                    // use内代码,是从下往上的顺序执行的
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        },
                        'less-loader'
                    ]
                },
                {
                    // js兼容性处理
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            [
                                '@babel/preset-env', {
                                    useBuiltIns: 'usage',
                                    corejs:
                                    {
                                        version: 3
                                    },
                                    targets: {
                                        // 浏览器兼容的版本
                                        chrome: '60',
                                        firefox: '50'
                                    }
                                }
                            ]
                        ]
                    }
    
                },
                {
                    //对图片进行打包处理
                    test: /\.(jpg|png|gif)$/,
                    loader: 'url-loader',
                    options: {
                        limit: 8 * 1024,
                        outputPath: 'imgs',
                        esModule: false
                    },
                    type: 'javascript/auto'
                },
                {
                    // 处理html中的图片文件
                    test: /\.html$/,
                    loader: 'html-loader',
                    options: {
                        esModule: false,
                    }
    
                },
                {
                    // 处理其他文件,如字体图标等
                    exclude: /\.(js|css|less|html|jpg|png|gif)$/,
                    loader: 'file-loader',
                    options: {
                        outputPath: 'media',
                        esModule: false,
                    },
                    type: 'javascript/auto'
                }
            ]
        }]    
    },
    plugins: [
        new minicssextractplugin({
            // 打包提取成单独文件
            filename: 'css/built.[contenthash:10].css'
        }),
        new cssminimizerwebpackplugin(
            // 压缩css文件
        ),
        new Htmlwebpackplugin({
            template: './src/index.html',
            // 压缩html
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        })
    ],
    // 生产环境下,js自动压缩
    mode: 'production'
}

5、package.json中代码

{
  "name": "webpack_production",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.16.5",
    "@babel/preset-env": "^7.16.5",
    "babel-loader": "^8.2.3",
    "core-js": "^3.21.1",
    "css-loader": "^6.5.1",
    "css-minimizer-webpack-plugin": "^3.3.1",
    "eslint": "^8.10.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-plugin-import": "^2.25.4",
    "eslint-webpack-plugin": "^3.1.1",
    "file-loader": "^6.2.0",
    "html-loader": "^3.0.1",
    "html-webpack-plugin": "^5.5.0",
    "less-loader": "^10.2.0",
    "mini-css-extract-plugin": "^2.4.5",
    "postcss-loader": "^6.2.1",
    "postcss-preset-env": "^7.1.0",
    "style-loader": "^3.3.1",
    "url-loader": "^4.1.1",
    "webpack": "^5.65.0",
    "webpack-cli": "^4.9.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "sideEffects": [
    "*.css"
  ]
}

注意:为了能够识别ES6模块,需要下载core-js包。输入npm i core-js -D然后输入npm run build即可进行打包。

最后打包成功的built.js中只包含了引入并使用的mul函数,未被引入和使用的count函数并没有被打包进来。 

 

二、code split(代码分割)

第一种方法

代码分割会把打包的一个大文件分割成多个不同的文件,这样在加载的时候就会并行加载,速度更快。还可以实现按需下载。

1、复制上一小节工程文件,并重命名。

在src下的js文件夹中有两个.js文件,我们以往打包是最后只生成了一个built.js文件,如果想生成两个呢。

2、首先修改index.js代码,去除引入的test.js代码

import '../css/index.css';
// 引入icon-font样式文件
import '../iconfit/iconfont.css';


function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}

console.log(sum(1, 2, 3, 4));

2、修改webpck.config.js代码

const { resolve } = require('path');
const minicssextractplugin = require('mini-css-extract-plugin');
const cssminimizerwebpackplugin = require('css-minimizer-webpack-plugin');
const Htmlwebpackplugin = require('html-webpack-plugin');

// css浏览器兼容性处理,默认是运行在生产环境下,若要运行于开发环境,还需做以下代码
process.env.NODE_ENV = 'production'

// tree shaking:去除无用代码
//前提: 1.必须使用ES6模块化2.开启production环境
//作用:减少代码体积
//在package.json中配置"sideEffects" : false所有代码都没有副作用(都可以进行tree shaking)
//问题:可能会把css/@babel/polyfill (副作用)文件干掉,因为这些文件都是引入了,但没有直接使用
//,所以需要配置为"sideEffects" : ["*.css"]

module.exports = {
    entry: {
        // 把之前的单入口修改为多入口
        // 有几个入口,打包就生成几个built.js
        index: './src/js/index.js',
        test: './src/js/test.js'
    },
    output: {
        // [name]:取entry中的入口文件名进行命名
        filename: 'js/[name].[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [{
            // oneOf 是每一个文件,只匹配到一个loader即可,
            // 不像之前,每个文件都要把下列loader全部匹配一遍
            // 注意不能有两个loader处理同一个类型文件
            oneOf: [
                {
                    // 检测css文件,并打包
                    test: /\.css$/,
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 对css做兼容性处理
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        }
                    ]
                },
                {
                    // 检测less文件,并打包
                    test: /\.less$/,
                    // use内代码,是从下往上的顺序执行的
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        },
                        'less-loader'
                    ]
                },
                {
                    // js兼容性处理
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            [
                                '@babel/preset-env', {
                                    useBuiltIns: 'usage',
                                    corejs:
                                    {
                                        version: 3
                                    },
                                    targets: {
                                        // 浏览器兼容的版本
                                        chrome: '60',
                                        firefox: '50'
                                    }
                                }
                            ]
                        ]
                    }
    
                },
                {
                    //对图片进行打包处理
                    test: /\.(jpg|png|gif)$/,
                    loader: 'url-loader',
                    options: {
                        limit: 8 * 1024,
                        outputPath: 'imgs',
                        esModule: false
                    },
                    type: 'javascript/auto'
                },
                {
                    // 处理html中的图片文件
                    test: /\.html$/,
                    loader: 'html-loader',
                    options: {
                        esModule: false,
                    }
    
                },
                {
                    // 处理其他文件,如字体图标等
                    exclude: /\.(js|css|less|html|jpg|png|gif)$/,
                    loader: 'file-loader',
                    options: {
                        outputPath: 'media',
                        esModule: false,
                    },
                    type: 'javascript/auto'
                }
            ]
        }]    
    },
    plugins: [
        new minicssextractplugin({
            // 打包提取成单独文件
            filename: 'css/built.[contenthash:10].css'
        }),
        new cssminimizerwebpackplugin(
            // 压缩css文件
        ),
        new Htmlwebpackplugin({
            template: './src/index.html',
            // 压缩html
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        })
    ],
    // 生产环境下,js自动压缩
    mode: 'production'
}

最后打包生成的文件,这就是对js文件进行了代码分割,通过修改入口文件的方法。  

 

第二种方法

1、我们将config.js代码的入口文件改回一个,并使用一个内置的配置splitChunks开启代码分割功能

const { resolve } = require('path');
const minicssextractplugin = require('mini-css-extract-plugin');
const cssminimizerwebpackplugin = require('css-minimizer-webpack-plugin');
const Htmlwebpackplugin = require('html-webpack-plugin');

// css浏览器兼容性处理,默认是运行在生产环境下,若要运行于开发环境,还需做以下代码
process.env.NODE_ENV = 'production'

// tree shaking:去除无用代码
//前提: 1.必须使用ES6模块化2.开启production环境
//作用:减少代码体积
//在package.json中配置"sideEffects" : false所有代码都没有副作用(都可以进行tree shaking)
//问题:可能会把css/@babel/polyfill (副作用)文件干掉,因为这些文件都是引入了,但没有直接使用
//,所以需要配置为"sideEffects" : ["*.css"]

module.exports = {
    entry: './src/js/index.js',
    output: {
        // [name]:取entry中的入口文件名进行命名
        filename: 'js/[name].[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [{
            // oneOf 是每一个文件,只匹配到一个loader即可,
            // 不像之前,每个文件都要把下列loader全部匹配一遍
            // 注意不能有两个loader处理同一个类型文件
            oneOf: [
                {
                    // 检测css文件,并打包
                    test: /\.css$/,
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 对css做兼容性处理
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        }
                    ]
                },
                {
                    // 检测less文件,并打包
                    test: /\.less$/,
                    // use内代码,是从下往上的顺序执行的
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        },
                        'less-loader'
                    ]
                },
                {
                    // js兼容性处理
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            [
                                '@babel/preset-env', {
                                    useBuiltIns: 'usage',
                                    corejs:
                                    {
                                        version: 3
                                    },
                                    targets: {
                                        // 浏览器兼容的版本
                                        chrome: '60',
                                        firefox: '50'
                                    }
                                }
                            ]
                        ]
                    }
    
                },
                {
                    //对图片进行打包处理
                    test: /\.(jpg|png|gif)$/,
                    loader: 'url-loader',
                    options: {
                        limit: 8 * 1024,
                        outputPath: 'imgs',
                        esModule: false
                    },
                    type: 'javascript/auto'
                },
                {
                    // 处理html中的图片文件
                    test: /\.html$/,
                    loader: 'html-loader',
                    options: {
                        esModule: false,
                    }
    
                },
                {
                    // 处理其他文件,如字体图标等
                    exclude: /\.(js|css|less|html|jpg|png|gif)$/,
                    loader: 'file-loader',
                    options: {
                        outputPath: 'media',
                        esModule: false,
                    },
                    type: 'javascript/auto'
                }
            ]
        }]    
    },
    plugins: [
        new minicssextractplugin({
            // 打包提取成单独文件
            filename: 'css/built.[contenthash:10].css'
        }),
        new cssminimizerwebpackplugin(
            // 压缩css文件
        ),
        new Htmlwebpackplugin({
            template: './src/index.html',
            // 压缩html
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        })
    ],
    // 代码分割的配置,可以将node_modules中代码单独打包一个chunk输出
    // 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk输出
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    },
    // 生产环境下,js自动压缩
    mode: 'production'
}

2、然后修改index.js代码,增加一个官方的node_modules(jquery)。

import '../css/index.css';
// 引入icon-font样式文件
import '../iconfit/iconfont.css';
// 引入jquery
import $ from 'jquery';


function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}

console.log($);

console.log(sum(1, 2, 3, 4));

3、然后安装jquery,npm i jquery --save,最后打包npm run build

会将自己编写的index.js和jquery有关的js分开生成,即生成两个.js文件。

 

第三种方法

第三种方法是通过修改index.js文件实现的,import动态导入语法,能将某个文件单独打包,config.js中入口还是修改为单入口

我们希望除了官方的node_modules,其他使用的js文件也可以被分割打包出来

1、首先把config.js中的第二种方法使用的插件去掉。

const { resolve } = require('path');
const minicssextractplugin = require('mini-css-extract-plugin');
const cssminimizerwebpackplugin = require('css-minimizer-webpack-plugin');
const Htmlwebpackplugin = require('html-webpack-plugin');

// css浏览器兼容性处理,默认是运行在生产环境下,若要运行于开发环境,还需做以下代码
process.env.NODE_ENV = 'production'

// tree shaking:去除无用代码
//前提: 1.必须使用ES6模块化2.开启production环境
//作用:减少代码体积
//在package.json中配置"sideEffects" : false所有代码都没有副作用(都可以进行tree shaking)
//问题:可能会把css/@babel/polyfill (副作用)文件干掉,因为这些文件都是引入了,但没有直接使用
//,所以需要配置为"sideEffects" : ["*.css"]

module.exports = {
    entry: './src/js/index.js',
    output: {
        // [name]:取entry中的入口文件名进行命名
        filename: 'js/[name].[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [{
            // oneOf 是每一个文件,只匹配到一个loader即可,
            // 不像之前,每个文件都要把下列loader全部匹配一遍
            // 注意不能有两个loader处理同一个类型文件
            oneOf: [
                {
                    // 检测css文件,并打包
                    test: /\.css$/,
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 对css做兼容性处理
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        }
                    ]
                },
                {
                    // 检测less文件,并打包
                    test: /\.less$/,
                    // use内代码,是从下往上的顺序执行的
                    use: [
                        minicssextractplugin.loader,
                        'css-loader',
                        {
                            // 还需要在package.json中定义browserslist
                            loader: 'postcss-loader',
                            options: {
                                postcssOptions: {
                                    plugins: [require('postcss-preset-env')()]
                                }
                            }
                        },
                        'less-loader'
                    ]
                },
                {
                    // js兼容性处理
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            [
                                '@babel/preset-env', {
                                    useBuiltIns: 'usage',
                                    corejs:
                                    {
                                        version: 3
                                    },
                                    targets: {
                                        // 浏览器兼容的版本
                                        chrome: '60',
                                        firefox: '50'
                                    }
                                }
                            ]
                        ]
                    }
    
                },
                {
                    //对图片进行打包处理
                    test: /\.(jpg|png|gif)$/,
                    loader: 'url-loader',
                    options: {
                        limit: 8 * 1024,
                        outputPath: 'imgs',
                        esModule: false
                    },
                    type: 'javascript/auto'
                },
                {
                    // 处理html中的图片文件
                    test: /\.html$/,
                    loader: 'html-loader',
                    options: {
                        esModule: false,
                    }
    
                },
                {
                    // 处理其他文件,如字体图标等
                    exclude: /\.(js|css|less|html|jpg|png|gif)$/,
                    loader: 'file-loader',
                    options: {
                        outputPath: 'media',
                        esModule: false,
                    },
                    type: 'javascript/auto'
                }
            ]
        }]    
    },
    plugins: [
        new minicssextractplugin({
            // 打包提取成单独文件
            filename: 'css/built.[contenthash:10].css'
        }),
        new cssminimizerwebpackplugin(
            // 压缩css文件
        ),
        new Htmlwebpackplugin({
            template: './src/index.html',
            // 压缩html
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        })
    ],
    // 代码分割的配置,可以将node_modules中代码单独打包一个chunk输出
    // 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk输出
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    },
    // 生产环境下,js自动压缩
    mode: 'production'
}

2、修改index.js代码,import动态导入语法,能将某个文件单独打包

import '../css/index.css';
// 引入icon-font样式文件
import '../iconfit/iconfont.css';


function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}

console.log(sum(1, 2, 3, 4));

// 通过js代码,实现代码分割功能。以ES10的方法引入test.js
// import动态导入语法,能将某个文件单独打包
// webpackChunkName:'test'表示打包后的文件名为test
import(/*webpackChunkName:'test'*/'../js/test')
  .then((result) => {
    console.log(result);
  })
  .catch(() => {
    console.log('文件加载失败~');
  })

3、输入npm run build打包


注:笔记转载自疯子的梦想@博客,课程来自尚硅谷b站Webpack5实战课程

posted @ 2022-03-08 11:21  柳洁琼Elena  阅读(66)  评论(0编辑  收藏  举报