webpack5的入门笔记

发布于:2023-01-17 ⋅ 阅读:(498) ⋅ 点赞:(0)

webpack5的入门笔记

1.入口和出口的配置文件webpack.config.js

//1.入口文件和出口文件跟webpack4一样
const path = require('path')
module.exports = {
  mode: 'development',//生成环境是production
  //入口文件
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
 

2.loader的使用

  1. css-loader
    1. css-loader的使用要配合style-loader 在项目中的配置文件webpack.config.js来配置

    2. 下载css-loader和style-loader

      //在 module中配置loader
       module: {
          rules: [
            {
              test: /\.css$/i,
              use: ["style-loader", "css-loader"], //loader是从右向左解析的
            },
          ],
        },
      
  2. less-loader
    1. 你需要先安装 lessless-loader

      npm install less less-loader --save-dev
      
    2. 配置

      module: {
          rules: [
            {
              test: /\.css$/i,
              use: ["style-loader", "css-loader"],
            }, {
              test: /\.less$/i,
              use: ["style-loader", "css-loader", "less-loader"]
            }
          ]
        },
      
  3. postcss-loader是一款使用插件去转换CSS的工具
    1. 要安装 postcss-loaderpostcss

      npm install --save-dev postcss-loader postcss
      
    2. 安装一个autoprefixer自动补全插件

      npm i -D postcss-loader
      
    3. 配置 在css-loader or less-loader or sass-loader之前添加postcss-loader

      {
          test: /\.css$/i,
              use: ["style-loader", "css-loader", "postcss-loader"],
      },
      //或者是
      {
           test: /\.css$/i,
           use: ["style-loader", "css-loader","less-loader" "postcss-loader"],
      }
      
    4. 需要一个postcss的配置文件postcss.config.js

      module.exports = {
        plugins: [
          require('autoprefixer')
        ]
      }
      
    5. webpack5中就不用autoprefixer要安装一个postcss-preset-env插件

      npm install postcss-preset-env
      
    6. 在postcss.config.js中配置插件

      module.exports = {
        plugins: [require('postcss-preset-env')]
      }
      
    7. 在package.json中添加浏览器的版本控制

        "browserslist": [
          "last 1 version",
          "> 1%", //兼容的比例
          "maintained node versions",
          "not dead"
        ]
      
    8. 如果一个样表中引入了另外一个样式表,则需要在加载的loader修改一个options参数

          rules: [
            {
              test: /\.css$/i,
              use: ["style-loader", {
                loader: "css-loader",
                options: {
                  importLoaders: 2,
                  esModule: true,
                },
      
              }, "postcss-loader", "less-loader"],
            }
          ]
      
  4. 图片处理的loader
    1. file-loader可以指定要复制和放置资源文件的位置

      1. 下载

        npm install file-loader --save-dev
        
      2. 配置

        module.exports = {
          module: {
            rules: [
              {
                test: /\.(png|jpg|gif)$/,
                use: [
                  {
                    loader: 'file-loader',
                    options: {
                      name: '[name].[ext]'
                    },
                  },
                ],
              },
            ],
          },
        };
        
    2. url-loader

      1. url-loader 允许你有条件地将文件转换为内联的 base-64 URL (当文件小于给定的阈值)

        npm install url-loader --save-dev
        
      2. 配置

        rules: [
            {
                test: /\.(png|jpg|gif)$/i,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192 //最大阈值
                        }
                    }
                ]
            }
        ]
        
    3. 在webpack5中使用资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。

      1. 资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader

        1. asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
        2. asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
        3. asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
      2. 配置图片资源加载对应的是file-loader

         {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource',
                generator: {
                  filename: 'image/[name]-[hash:4].[ext][query]'
                }
              },
        
      3. 将图片处理为data URl的形式使用type:asset/inline对应的是url-loader

        {
            test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/inline',
        },
        
      4. 将type设置为type:asset,webpack 将按照默认条件,自动地在 resourceinline 之间进行选择

         {
             test: /\.(png|svg|jpg|jpeg|gif)$/i,
             type: 'asset',
             generator: {
                 filename: 'image/[name].[ext]'
              },
               parser: {
                   dataUrlCondition: {
                       maxSize: 70 * 1024
                    }
              }
         },
        
      5. 加载字体图标

        {
            test: /\.(woff|woff2|eot|ttf|otf)$/i,
            type: 'asset/resource',
            generator: {
                filename: 'font/[name].[hash:3][ext]'
           }
        },
        

3.webpack 中插件的使用

  1. clean-webpack-plugin 清除打包文件插件
   ```js
   npm install --save-dev clean-webpack-plugin
   ```

  1. 在webpack.config.js中引入和配置

     ```js
     const CleanWebpackPlugin = require('clean-webpack-plugin');
      plugins: [
         new CleanWebpackPlugin()
       ]
     ```
  1. html-webpack-plugin插件的使用

    1. 下载安装

      npm install --save-dev html-webpack-plugin
      
    2. 导入插件和配置

      const HtmlWebpackPlugin = require('html-webpack-plugin');
        plugins: [
          new HtmlWebpackPlugin(
            {
              title: 'webpack的插件使用',//配置的title
              template: './public/index.html',//使用的模板
            }
          ),
          new CleanWebpackPlugin()
        ]
      
  2. DefinePlugin 允许在 编译时 将你代码中的变量替换为其他值或表达式

    1. 这个插件是webpack的内置的一个插件

    2. 使用方法

      //导入
      const { DefinePlugin } = require('webpack')
      //配置
      new DefinePlugin({  //常量的配置使用的是键值对的形式
            BASE_URL: "'./'"  //.icon的路径
       })
      

4.babel-loader的使用

  1. babel-loader是将ES6代码转为ES6

  2. 使用方法

    1. 安装相关的loader

      npm install -D babel-loader @babel/core @babel/preset-env
      
    2. 先关的配置

       {
           test: /\.js$/,
               exclude: /(node_modules|bower_components)/, //排除node_modules这么目录
                   use: {
                       loader: 'babel-loader',
                           options: {
                               presets: ['@babel/preset-env']
                           }
                   }
       }
      
    3. 也可以单独抽离出一个babel.config.js的配置文件

      //babel.config.js配置文件
      module.exports = {
        presets: ['@babel/preset-env']
      }
      //在webpack.config.js中可以是配置loader了
      {
          test: /\.js$/,
          exclude: /(node_modules|bower_components)/,
          use: ['babel-loader']
      }
      

5.polyfill的使用

  1. polyfill是babel-loaer的补充,兼容更高级的语法,在webpack中polyfill是单独的包,如果要使用则要按需加载

  2. 在bable7.4.0以上建议引入"core-js/stable"和regenerator-runtime/runtime.

  3. 安装先关依赖

    npm install core-js regenerator-runtime
    
  4. 在babel.config.js中配置

    module.exports = {
      presets: [["@babel/preset-env", {
        useBuiltIns: 'usage', //'usage'根据用户当前源代码使用的新语法来填充,'entry'根据当前筛选的浏览器来填充;默认的值的'fasle'
        corejs: 3
      }]]
    }
    

6.CopyWebpackPlugin插件的使用

  1. 安装插件

    npm install copy-webpack-plugin --save-dev
    
  2. 在webpack.config.js中的配置

    new CopyPlugin({
        patterns: [
            {
               from: 'public',//拷贝的目录
               globOptions: {//排除不需要拷贝的内容
                    ignore: ['**/index.html']
                }
            }
        ]
    })
    

7.webpack-dev-server

  1. webpack-dev-server是提供一个简易的web服务,修改代码可以实时加载

  2. 下载npm install --save-dev webpack-dev-server

  3. 配置

    module.exports = {
      devServer: {
        static: './dist', //服气器查找的文件位置
      },
    }
    
  4. 在package.json中添加配置

    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
            "start": "webpack-dev-server --open", // 使用npm run start 启动服务
    },
    

8.模块热替换HRM

  1. 作用是在运行是更新各种模块,无需进行完全刷新

  2. 使用方法

    1. 在webpack.config.js中引入插件

      具体使用查看

    2. 在模块是使用

      if (module.hot) {
        module.hot.accept('./js/print.js', function () {
          console.log('加载的模块print');
          printMe()
        })
      }
      

9.devServer中的代理设置

  1. webpack中的devServer默认就是开启了一个服务

    devServer: {
        port: 8080, // 源地址端口,自行修改
        proxy: {
          '/': {
            target: 'http://localhost:3000',  // 跨域目标主机,自行修改
            ws: true,  // 代理 websockets
            changeOrigin: true,
            pathRewrite: {
              '^/api': ''  // 重写地址
            }
          },
    
        }
      }
    

10.source map的使用

  1. 为了更容易地追踪 error 和 warning,JavaScript 提供了 source maps功能,可以将编译后的代码映射回原始源代码
  2. Devtool此选项控制是否生成,以及如何生成 source map。
  3. 配置: devtool: 'source-map', devtool的默认值是eval
  4. devtool对应的值以及作用
    1. 默认值是eval生成的代码是没有映射
    2. 值为source-map生成.map的文件,与原代码生成一个映射关系,可以方便的查找代码的报错位置
    3. 值为eval-source-map打包的代码没有一个.map的映射文件,但是代码可以中可以查找到报错位置
    4. 值为inline-source-map时打包代码没有一个.map的映射文件
    5. 值为cheap-source-map,报错只提供行信息,不提供列信息
    6. 值为cheap-module-source-map报错信息精确到行和列
    7. 值为hidden-source-map,隐藏了.map文件
    8. 在是实际开发中常用的是source-mapcheap-nodeule-source-map

11.webpack对typescript打包的使用

  1. 下载先关依赖

    npm install --save-dev typescript ts-loader
    
  2. 在项目的根目录中配置tsconfig.json的配置文件

    {
      "compilerOptions": {
        "outDir": "./dist/",
        "noImplicitAny": true,
        "module": "es6",
        "target": "es5",
        "allowJs": true,
        "moduleResolution": "node"
      }
    }
    
  3. 在webpack.config.js中配置loader

     rules: [
          {
            test: /\.ts?$/,
            use: 'ts-loader',
            exclude: /node_modules/,
          },
        ],
    
  4. 但是ts-loader只是把ts转为js,但是对于想Promise这类的内容没有填充转换,所以在这要使用babe中对ts的预设@babel/preset-typescript

    1. 下载@babel/preset-typescript

      npm install --save-dev @babel/preset-typescript
      
    2. .babel.config.js配置预设

      module.exports = {
        presets: [
          ["@babel/preset-env", {
            useBuiltIns: 'usage',
            corejs: 3
          }
          ],
          ["@babel/preset-typescript"] //ts的预设配置
        ]
      }
      
    3. 这时就不用ts-loader了,要使用babel-loader

      {
          test: /\.ts?$/,
          use: ['babel-loader'],
          exclude: /node_modules/,
      },
      
    4. 使用ts-loader可以对ts语法进行校验,babel-loader不能对ts语法校验,因此在需要对ts语法做校验又要使用babel-loadr,可以在webpack.json中配置一个命令

        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          "build": "npm run tsc && webpack", //打包前先校验语法
          "start": "webpack serve",
          "tsc":"tsc --noEmit" //校验ts语法
        },
      

12.区分打包环境

  1. 环境的区分

    1. 生成环境和开发环境的区分,在webpack4+中通过mode的值来区分,production生成环境,development是开发环境

    2. package.json中的可以通过配置参数来获取当前的环境变量

      
        "scripts": {
          "build": "npm run ck && webpack",
          "build1":"webpack --config webpack.base.js --env production", //--env production环境参数
          "build2":"webpack --config webpack.base.js --env development",//--env production环境参数
          "start": "webpack serve",
          "ck": "tsc"
        },
      

      这是在webpack.base.js通过参数的形式获取

      module.exports = (env) => {
        console.log(env, '<---------------')
      }
      //打印的参数是:{ WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, development: true } <---------------
      //这就可以获取传递的参数
      
  2. webpack.config.js的拆分

    1. 拆分一个开发环境,生成环境和一个公共的配置文件

      //生产环境的webpack
      module.exports = {
        mode: 'production',//'development'||'production'
        devtool: '', //此选项控制是否生成,以及如何生成 source map。
      }
      
      //开发环境的webpack配置
      module.exports = {
        mode: 'development',//'development'||'production'
        devtool: 'cheap-module-source-map', //此选项控制是否生成,以及如何生成 source map。
        target: "web",
        devServer: {
          static: './dist',
          hot: true,
          compress: true
        },
      }
      
      
      //webpack代码抽离的公共部分
      const path = require('path')
      const { CleanWebpackPlugin } = require('clean-webpack-plugin')
      const HtmlWebpackPlugin = require('html-webpack-plugin')
      const { DefinePlugin, HotModuleReplacementPlugin } = require('webpack')
      const CopyPlugin = require("copy-webpack-plugin");
      const { merge } = require('webpack-merge'); //用于代码的合并
      //导入pro.js 和 dev.js
      const proConfig = require('./webpack.pro.js');
      const devConfig = require('./webpack.dev.js')
      //抽离的公共的配置
      const baseConfig = {
        entry: './src/main.ts',
        output: {
          path: path.resolve(__dirname, 'dist'),
          filename: 'main.js'
        },
        resolve: {
          extensions: ['.js', '.json', '.ts', '.vue'],
          alias: {
            "@": path.resolve(__dirname, 'src')
          }
        },
        module: {
          rules: [
            {
              test: /\.css$/i,
              use: ["style-loader", "css-loader", "postcss-loader"],
            },
            {
              test: /\.(png|svg|jpg|jpeg|gif)$/i,
              type: 'asset',
              generator: {
                filename: 'image/[name].[ext]'
              },
              parser: {
                dataUrlCondition: {
                  maxSize: 40 * 1024
                }
              }
            },
            {
              test: /\.(woff|woff2|eot|ttf|otf)$/i,
              type: 'asset/resource',
              generator: {
                filename: 'font/[name].[hash:3][ext]'
              }
            }, {
              test: /\.js$/,
              exclude: /(node_modules|bower_components)/,
              use: ['babel-loader']
            },
            {
              test: /\.ts$/,
              use: ['babel-loader'],
              exclude: /node_modules/,
            },
          ],
        },
        plugins: [
          new HtmlWebpackPlugin(
            {
              title: 'webpack的插件使用',
              template: './public/index.html',
            }
          ),
          new CleanWebpackPlugin(),
          new DefinePlugin({  //常量的配置使用的是键值对的形式
            BASE_URL: "'./'"
          }),
          new CopyPlugin({
            patterns: [
              {
                from: 'public', globOptions: {
                  ignore: ['**/index.html']
                }
              }
            ]
          }),
          //热更新插件
          new HotModuleReplacementPlugin()
        ],
      }
      
      module.exports = (env) => {
        //定义一个变量接收参数
        const isProduction = env.production
        const comConfig = isProduction ? merge(proConfig, baseConfig) : merge(devConfig, baseConfig)
        return comConfig //根据不同的环境导出不同的模式
      }
      

13.代码的拆分

  1. 方式1,多入口的方式

    //使用多入口的方式打包  
    entry: {
        index: './src/main.js', 
        other: './src/other.js'
      },
      //输入的文件的文件名使用`[name].js`
      output: {  //出口文件,是绝对路径,要是用node的path模块
        path: path.resolve(__dirname, './dist/'),
        filename: '[name].js',
      },
    
  2. 如果代码依赖依赖第三方库代码的打包方式

      entry: {
        index: './src/index.js',
        index2: { import: './src/index2.js', dependOn: 'jquery' },
        jquery: "jquery"
      },
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
      },
    
  3. 若干代码依赖多个第三方库的打包方式

    const baseConfig = {
      entry: {
        index: './src/index.js',
        index2: { import: './src/index2.js', dependOn: 'shared' },
        shared: ['jquery', 'lodash']
      },
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
      },
    }
    
  4. 可以使用splitChunks插件进行拆包

      optimization: {
        minimizer: [
          new TerserPlugin({
            extractComments: false
          }),
        ],
        splitChunks: {
          runtimeChunk:true,//修改运行的代码,都会生成不同的的哈希值,没有修改的就不变
          chunks: 'initial', //chunks的值有`all`,'async'
          minSize: 20000,  //模块在压缩前的大小最小值,单位是字节
          minChunks: 1, //表示要被提取的模块最小被引用次数
          cacheGroups: { //
            vendors: {
              name: `chunk-vendors`,
              test: /[\\/]node_modules[\\/]/,
              priority: -10, //优先级
              chunks: 'initial'
            },
            common: {
              name: `chunk-common`,
              minChunks: 2,
              priority: -20,//优先级
              chunks: 'initial',
              reuseExistingChunk: true
            }
          }
    
        }
      },
    
  5. 使用import动态导入包

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到