webpack入门4----优化环境配置(上)

下方的配置代码,均为webpack.config.js文件的内容

如果需要产生打包文件的话,直接运行指令      webpack

如果需要直接运行的话,直接运行指令             webpack server   

项目内容上传到了  码云 https://gitee.com/a2547944268/webpack_test上,下面的内容对照着代码的话,可能更清晰。

优化配置概括

优化主要分为两个方面的配置:开发环境和生产环境

具体可以概括如下:

# webapck性能优化
* 开发环境性能优化
* 生产环境性能优化


# 开发环境性能优化
* 优化打包构建速度
  * HMR
* 优化代码调试
  * source-map


# 生产环境性能优化
* 优化打包构建速度
  * oneOf
  * babel缓存
  * 多进程打包
  * external
  * dll
* 优化代码运行的性能
  * 缓存(hash/chunkhash/contenthash) 及三者区别
  * tree shaking (es6/producton) sideEffect
  * code split(单/多入口)
  * 懒加载/预加载
  * pwa
  

1.HMR

HMR:hot module replacement 热模块替换

  作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)

            极大提升代码构建速度

  实现:

          样式文件:可以使用HMR功能,因为style-loader内部实现了

          js文件:默认不能使用HMR功能,需要修改js代码,添加支持HMR功能的代码

                  注意:HMR功能对js的处理,只能处理非入口js文件的其他文件

          html文件:默认不能使用HMR功能,同时会导致问题:html文件不能热更新了(不用做HMR功能,因为只有一个html文件)

                 解决:修改entry入口,将html文件引入

其实配置HMR,只需要在webpack.config.js内文件的derServer属性内添加  hot: true  便可直接开启HMR

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      // css文件是放置在js文件内的,不需要单独文件夹存放
      {
        // 处理css资源
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          // 关闭es6模块化
          esModule: false,
          outputPath: 'imgs',
        },
      },
      {
        // 处理html中img资源
        test: /\.html$/,
        loader: 'html-loader',
        options: {
          esModule: true,
        },
      },
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media',
        },
      },
    ],
  },
  plugins: [
    // plugins的配置
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    // 开启HMR
    // 当修改了webpack配置,新配置想要生效,必须重启webpack服务
    hot: true,
  },
};

运行指令为    webpack server

2.source-map

source-map主要是为了解决:开发环境下如何调试代码

source-map:一种 提供源代码到构建后代码映射 技术(如果构建后代码出错了,通过映射可以追踪)

    写法:  devtool: 'source-map'   是最基本的配置

    [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

    下面都是devtool的属性值:::

    source-map:外部  

        当文件内有报错的情况下,可以直接指定到具体文件

        错误代码的提示信息和源代码的错误位置

    inline-source-map:内联  

        只生成一个内联source-map

        错误代码的提示信息和源代码的错误位置

    hidden-source-map:外部

        可以提示到错误代码错误原因,但是没有错误位置

        不能追踪源代码,只能提示到构建后代码的错误位置

        隐藏源代码,防止代码泄露

    eval-source-map:内联 

        每个文件都生成对应的source-map,都在eval

        错误代码的提示信息和源代码的错误位置

    nosources-source-map:外部

        错误代码的提示信息,但是没有任何源代码信息

        隐藏源代码,防止代码泄露

    cheap-source-map:外部

        错误代码的提示信息和源代码的错误位置

        只能精确到行

    cheap-module-source-map:外部

        错误代码的提示信息和源代码的错误位置

        module会将loader的source map加入

    

     内联和外部的区别: 1.外部生成了文件,内联没有  2.内联构建速度更快

 开发环境

   需要的:速度快,调试更友好

        速度快(eval>inline>cheap>...)

        eval-cheap-source-map   速度会更快

        eval-source-map

      调试更友好

        source-map

        cheap-module-source-map

        cheap-source-map

      推荐:

      -->  eval-source-map    / eval-cheap-module-source-map

        优先选择第一种

生产环境

    生产环境需要的:源代码要不要隐藏,调试要更友好

        内联会让代码体积变得非常大,所以在生产不使用内联

        隐藏源代码

          hidden-source-map    只隐藏源代码,会提示构建后代码错误

          nosources-source-map   全部隐藏

    推荐

        --> source-map / cheap-module-source-map

webpack.config.js配置

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: ['./src/js/index.js','./src/index.html'],
    output: {
        filename: 'js/built.js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            // loader的配置
            {
                // 处理less资源
                test: /\.less$/,
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            // css文件是放置在js文件内的,不需要单独文件夹存放
            {
                // 处理css资源
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    plugins: [
        // plugins的配置
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ],
    mode: 'development',
    devServer: {
        contentBase: resolve(__dirname, 'build'),
        compress: true,
        port: 3000,
        open: true,
        // 开启HMR
        // 当修改了webpack配置,新配置想要生效,必须重启webpack服务
        hot: true
    },
    devtool: 'source-map'
};

3.oneOf

主要在module的rules属性内使用

主要目的:使用的文件loader只会匹配一个,主要用于提升构建速度

const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 这里默认使用生产环境,所以需要配置开发环境
// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'development'

// 复用loader
const commonCssLoader = [
    // 这种写法会将css代码直接整合到js内
    // 'style-loader',
    // 下面的写法是将编译后的css文件提取出来
    MiniCssExtractPlugin.loader,   // 将css代码提取为单独css文件
    'css-loader',   // 编译css代码
    {
        // css兼容性处理
        // 还需要在package.json中定义browserslist
        loader: 'postcss-loader',
        options: {
            ident: 'postcss',
            plugins: () => [
                require('postcss-preset-enev')()
            ]
        }
    },
]

module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'js/built.js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                // 优先执行
                enforce: 'pre',
                loader: eslint - loader,
                options: {
                    fix: true    // 自动修复js内的报错
                }
            },
            {
                // 以下loader只会匹配一个,主要用于提升构建速度
                // 注意:不能有两个配置处理同一种类型的文件
                oneOf: [
                    {
                        test: /\.css$/,
                        use: [
                            ...commonCssLoader
                        ]
                    },
                    {
                        test: /\.less$/,
                        use: [
                            ...commonCssLoader,
                            'less-loader'  // 将less编译成css
                        ]
                    },
                    {
                        // 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,
                            name: '[hash:10].[ext]',
                            outputPath: 'imgs',  // 输出路径
                            esModules: false
                        }
                    }, {
                        test: /\.html$/,
                        loader: 'html-loader'
                    },
                    {
                        // 处理其他文件
                        exclude: /\.(js|css|less|html|jpg|png|gif)/,
                        loader: 'file-loader',
                        options: {
                            outputPath: 'media'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/built.css'
        }),
        // 压缩css代码
        new OptimizeCssAssetsWebpackPlugin(),
        // 这个可以处理html里的代码,但是html内的图片无法处理
        new HtmlWebpackPlugin({
            template: './src/index.html',
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        })

    ],
    mode: 'production'
}

4.缓存

缓存主要是两点:babel、资源

       1. babel缓存

            cacheDirectory: true

            ---> 让第二次打包构建速度更快

        2.文件资源缓存

            需要修改文件名

            2.1 hash:每次webpack构建时会生成一个唯一的hash值

                问题:因为js和css同时使用一个hash值

                如果重新打包,会导致所有缓存失效(如果只改动了一个文件)

            2.2 chunkhash:根据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值就一样

                问题:js和css的hash值还是一样的

                   因为css是在js中被引入的,所以同属于同一个chunk

            2.3  contenthash:根据文件内容生成hash值,不同文件的hash值不一样

            --->让代码上线运行缓存更好使用

            三者的区别:

            hash在编译后都会生成新的hash值,无论值文件内容是否变化

            chunkhash:js和css绑定在一起了,值是一致的

整个配置文件太多了,但是可以参考上面的代码例子:

const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 这里默认使用生产环境,所以需要配置开发环境
// 定义nodejs环境变量:决定使用browserslist的哪个环境变量
process.env.NODE_ENV = 'development'


// 复用loader
const commonCssLoader = [
    // 这种写法会将css代码直接整合到js内
    // 'style-loader',
    // 下面的写法是将编译后的css文件提取出来
    MiniCssExtractPlugin.loader,   // 将css代码提取为单独css文件
    'css-loader',   // 编译css代码
    {
        // css兼容性处理
        // 还需要在package.json中定义browserslist
        loader: 'postcss-loader',
        options: {
            ident: 'postcss',
            plugins: () => [
                require('postcss-preset-enev')()
            ]
        }
    },
]

module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'js/built.[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                // 优先执行
                enforce: 'pre',
                loader: eslint-loader,
                options: {
                    fix: true    // 自动修复js内的报错
                }
            },
            {
                // 以下loader只会匹配一个,主要用于提升构建速度
                // 注意:不能有两个配置处理同一种类型的文件
                oneOf: [
                    {
                        test: /\.css$/,
                        use: [
                            ...commonCssLoader
                        ]
                    },
                    {
                        test: /\.less$/,
                        use: [
                            ...commonCssLoader,
                            'less-loader'  // 将less编译成css
                        ]
                    },
                    {
                        // js的兼容性处理
                        test: /\.js$/,
                        exclude: /node_modules/,
                        loader: babel-loader,
                        options: {
                            presets:[
                                [
                                    '@babel/preset-env',  // 全部加载的话很大,可以按需加载
                                    {
                                        useBuiltins: 'usage',
                                        corejs: {version: 3},
                                        targets: {
                                            chrome: '60',
                                            firefox: '50',
        
                                        }
                                    }
                                ]
                            ],
                            // 开启babel缓存
                            // 第二次构建时,才会读取之前的缓存
                            cacheDirectory: true
                        }
                    },
                    {
                        test: /\.(jpg|png|gif)/,
                        loader: 'url-loader',
                        options: {
                            limit: 8 *1024,
                            name: '[hash:10].[ext]',
                            outputPath: 'imgs',  // 输出路径
                            esModules: false
                        }
                    },{
                        test: /\.html$/,
                        loader: 'html-loader'
                    },
                    {
                        // 处理其他文件
                        exclude: /\.(js|css|less|html|jpg|png|gif)/,
                        loader: 'file-loader',
                        options: {
                            outputPath: 'media'
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/built.[contenthash:10].css'
        }),
        // 压缩css代码
        new OptimizeCssAssetsWebpackPlugin(),
        // 这个可以处理html里的代码,但是html内的图片无法处理
        new HtmlWebpackPlugin({
            template: './src/index.html',
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        })
        
    ],
    mode: 'production',
    devtool: 'source-map'
}

可以看到实现babel缓存的属性  cacheDirectory: true   及压缩css时文件缓存

5.tree shaking

tree shaking:去除无用代码

        前提:1.必须使用ES6模块  2.开启production环境

    作用:减少代码体积

    在package.json中配置

        "sideEffects": false   所有代码都没有副作用(都可以进行tree shaking)

        问题:可能会把css / @babel/polyfill(副作用)文件干掉

        如果不进行tree shaking(不希望删掉css等文件),可以修改:"sideEffects": ["*.css"]

 webpackconfig.js的内容与其他的类似,没发现具体差别,需要直接看gitee上的代码。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值