Webpack手册

177 阅读3分钟

Webpack5使用手册

安装

全局安装

npm i webpack webpack-cli -g

本地安装

npm i webpack webpack-cli -D

本地打包指令

npx webpack 
npx webpack --watch //监测变化并重新编译打包

使用配置文件进行打包

const path = require('path')
module.exports = {
  entry: './assets/js/main.js',   //入口文件
  output: {                       //出口文件及其路径
    filename: 'app.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
​
    ]
  },
  plugins: [
    //此处即为插件
  ],
  mode: 'development'
}

Plugin

定义

webpack中的plugin用于处理更宽广的业务。例如打包优化和压缩等功能性操作。具体内容看具体的插件

webpack官网中有三种类型的插件:社区的官方的第三方的

插件参考文献:webpack.js.org/plugins/

【社区】html-wepack-plugin

作用

生成一个html5文件,会在Body里面使用标签引入webpack生成的Bundle

安装指令

npm install html-webpack-plugin -D //本地安装

Webpack-dev-server

定义

提供一个基础web server,并具有实时重新加载的功能

指令

npm install webpack-dev-server -D   //本地安装
npx webpack-dev-server //启动

资源模块 Asset Modules

定义

它允许使用资源文件(字体,图标等)而无需配置额外 loader。

  • asset/resource:发送一个单独的文件并导出 URL

  • asset/inline:导出一个资源的 Data URI ( 64位图 )

  • asset/source:导出资源的源代码

  • asset:在导出一个资源的 Data URI 和发送一个单独的文件之间自动进行选择

    // js 文件导入
    import 命名 from '资源路径'// css 文件引用
    .box {
      background-image: url('资源路径');
    }
    

assets/resource 文件url

image-20220812124654626当前文件在assets中存在

webpack具体配置文件

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
        clean: true, //每次打包清除dist
        assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
    },
    mode: 'development', //设置开发模式
    devtool: 'inline-source-map',
    plugins: [
        //使用HtmlwebpackPlugin进行生成html文件,会自动引入webpack打包的bundle
        new HtmlWebpackPlugin({
            template: './index.html', //模板文件
            filename: 'app.html', //文件名称
            inject: 'body' //bundle插入的位置(默认为head)
        })
    ],
    devServer: {
        static: './dist' //静态路径
    },
    module: {
        rules: [{
                test: /.png$/, //.png结尾的文件
                type: 'asset/resource', //生成文件的url
                generator: { //文件生成路径以及文件名称【优先级会比assetModuleFilename要高】
                    filename: 'images/[contenthash][ext]'
                }
            },
            {
                test: /.svg$/,
                type: 'asset/inline', //生成文件的base64
            },
            {
                test: /.txt$/,
                type: 'asset/source', //生成文件的源代码
            }, {
                test: /.jpeg$/,
                type: 'asset', //系统根据文件大小自动选择resource 或者 inline 临界值8k >8k resouce ,<8k inline
                parser: {
                    dataUrlCondiction: {
                        maxSize: 4 * 1024 //临界值 8k
                    }
                }
            }
        ]
    }
}

loder

定义

webpack中管理资源模块,本来webpack只能处理js文件,通过loader可以加载转化其他文件进行打包处理。

加载css

npm install css-loader -D //本地安装css-loader 可处理css文件
npm install style-loader -D //style-loader 可将css样式放在页面上
npm install less-loader less -D //less-loader 以及 Less解析 处理less样式

配置文件

    module: {
        ...
        rules: [ {
               test: /.(css|less)$/,
                use: ['style-loader', 'css-loader']   //此处位置不能颠倒,是从后往前加载的。需要先用css-loader来加载css文件,再用style-loader将css样式放置在页面标签上,
          // use: ['style-loader', 'css-loader', 'less-loader'] less-loader最后,先用Less-loader解析css文件,将结果给css文件,css文件在将结果给style-loader
          
            }
        ]
    }

抽离css和压缩css

npm install mini-css-extract-plugin -D //本地抽离css文件压缩css
npm i css-minimizer-webpack-plugin -D //本地压缩css 在生产环境模式下使用 有助于css加载效率

配置文件

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
    ...
    mode: 'production', //设置开发模式
    devtool: 'inline-source-map',
    plugins: [
        ...
        new MiniCssExtractPlugin({
            filename: 'style/[contenthash].css'
        })
    ],
    optimization: { //优化配置
        minimizer: [
            new CssMinimizerPlugin() //将model改为production 
        ]
    }
}

加载字体与csv、xml文件(JSON可以直接打包无需插件)

指令

npm install csv-loader -D 
npm install xml-loader -D

配置文件

    module: {
        ...
        rules: [ {
               test: /.(woff|woff2|eot|ttf|otf)$/,
               type:'asset/resource'
            },{
               test: /.(csv|tsv)$/,
               type:'csv-loader'
            },{
               test: /.xml$/,
               type:'xml-loader'
            }
        ]
    }

babel-loader

用处:打包时将Es6转换为低版本Es代码,让其他浏览器也能正常运行。

  • babel-loader: 在 webpack 里应用 babel 解析 ES6 的桥梁
  • @babel/core: babel 核心模块
  • @babel/preset-env: babel 预设,一组 babel 插件的集合

指令

npm i babel-loader @babel/core @babel/preset-env -D   //本地安装babel的三个模块

配置

{//module节点下
  test: /.\js$/,
    exclude:/node_modules/, //过滤掉node_modules里面的
    use: {
      loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']    //设置预设
        }
    }
}

注意:

regeneratorRuntime 是 webpack 打包生成的全局辅助函数,由 babel 生成,用于兼容 async/await 的语法。

npm i @babel/runtime @babel/plugin-transform-runtime -D   //安装regeneratorRuntime  辅助函数

新增配置

module.exports = {
  ...
  module: {
    rules: [
      {
        test: /.m?js$/,
        // 排除 node_modules 中安装的库
        exclude: /(node_modules|bower_components)/,
        use: {
          // 加载 loader
          loader: 'babel-loader',
          options: {
            // 配置预设
            presets: ['@babel/preset-env']
            plugins: [
              [
                '@babel/plugin-transform-runtime'
              ]
            ]
          }
        }
      }
    ]
  }
}

代码分离

webpack中最引入注目的一个功能特性,可以将代码分离到不同的Bundle中,然后进行按需加载或者并行加载。使用得当可以极大的提升加载速率、以下为常用三种方法。

配置入口节点

使用entry手动分离代码,但会有问题。如果多个入口,这些多个入口共享的文件会在每个包里面重复打包。

module.exports = {
    entry: { //配置多入口
        index: './src/index.js',
        another: './src/another-modules.js'
    },
    output: {
        filename: '[name].bundle.js', //对应多入口进行出口文件分离
        path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
        clean: true, //每次打包清除dist
        assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
    },
   }

📢:如果在多入口文件中引用相同的包,比如lodash。打包成两个bundle后会发现,lodash被重复打包了。

防止重复打包

使用entry dependencies 或者 splitChunksPlugin去重和分离代码

入口依赖 entry dependencies
moudle.exports = {
      entry: { //配置多入口
        index: {
            import: './src/index.js',
            dependOn: 'shared' //可以共享资源
        },
        another: {
            import: './src/another-modules.js',
            dependOn: 'shared'
        },
        shared: 'lodash' //设置共享的资源 shared为自定义Key值
    },
        output: {
        filename: '[name].bundle.js', //对应多入口进行出口文件分离 
        path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
        clean: true, //每次打包清除dist
        assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
    },
}
//输出结果 index.bundle.js another.bundle.js shared.bundle.js
//会将index、another中的lodash 分离出来 打包成为shared.bundle.js
splitChunks 自动分离
module.exports = {
    entry: { //配置多入口
        // index: {
        //     import: './src/index.js',
        //     dependOn: 'shared' //可以共享资源
        // },
        // another: {
        //     import: './src/another-modules.js',
        //     dependOn: 'shared'
        // },
        // shared: 'lodash' //设置共享的资源
        index: './src/index.js',
        another: './src/another-modules.js'
    },
    ...
    optimization: { //优化配置
        minimizer: [
            new CssMinimizerPlugin() //将model改为production 
        ],
        splitChunks: { //自动抽离相同资源代码 Lodash这种
            chunks: 'all'
        }
    }
}
​
//输出结果 会多出两个bundle vendor/babel runtime helper bundle.js 发现index another中体积小了很多

动态导入

通过模块import内联函数来分离代码

懒加载

定义:也叫按需加载,可以极大优化首页加载的速度

//index.js
const addButton = document.createElement('button')
addButton.textContent = "执行加法运算"
//添加事件 通过动态导入的方式
addButton.addEventListener('click', () => {
    //使用魔法值修改math.js打包后的bundle名字
    import( /* webpackChunkName:'math'*/ './math').then(({
        add
    }) => {
        alert(add(4, 5))
    })
})
//将button放置在页面上
document.body.appendChild(addButton)

注意📢:只有在按钮被点击后math.bundle.js才会被网络加载,效果非常好

预获取/预加载

  • 预获取prefetch:将来某些导航可能需要的资源

    • 在浏览器network中看到文件会被导入,但element标签中发现多了一个。这种加载是在所有资源加载完之后,网络空闲时间,再进行加载
    • 使用效果会比预加载或者懒加载要好
  • 预加载preload:当前导航下可能需要的资源

    • 与懒加载类似

缓存

    output: {
        filename: '[name].[contenthash].js', //对应多入口进行出口文件分离
        path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
        clean: true, //每次打包清除dist
        assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
    },

【缓存业务文件】出口bundel文件 根据contentdash修改文件名称,可以让浏览器缓存更新

【缓存第三方】一般不变的资源,可以提高首屏加载速度,节省网络流量

module.exports = {
  ...
  splitChunks: {
    cacheGroups: {
      vendor: {
        test: /[\/]node_modules[\/]/,
        name: 'vendors',
        chunks: 'all'
      }
    }
  }
}

【将所有打包出来的js放到一个目录下】

module.exports = {
  ...
      output: {
        filename: 'sciprts/[name].[contenthash].js', //对应多入口进行出口文件分离 直接加路径即可
        ...
    },
}

\