Webpack4从入门到精通以及和webpack5对比_webpack现在用的是哪个版本

news2024/12/26 13:19:11
3.1 打包样式资源css-loaderstyle-loader
 {
        // 匹配哪些文件
        test: /\.less$/,
        // 使用哪些loader进行处理
        use: [
          // use数组中loader执行顺序:从右到左,从下到上,依次执行(先执行css-loader)
          // style-loader:创建style标签,将js中的样式资源插入进去,添加到head中生效
          'style-loader',
          // css-loader:将css文件变成commonjs模块加载到js中,里面内容是样式字符串
          'css-loader',
          // less-loader:将less文件编译成css文件,需要下载less-loader和less
          'less-loader'
        ],
      },


      {
        test: /\.css$/,
        //使用多个loader用use,使用一个loader用loader
        use: ['style-loader', 'css-loader'],
      },

3.2 打包 html 资源HtmlWebpackPlugin
  // plugin的配置
  plugins: [
    // html-webpack-plugin:默认会创建一个空的html文件,自动引入打包输出的所有资源(JS/CSS)
    // 需要有结构的HTML文件可以加一个template
    new HtmlWebpackPlugin({
      // 复制这个./src/index.html文件,并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html',
    }),
  ],

3.3 打包图片资源url-loaderhtml-loader
  • url-loader:处理图片资源,问题:默认处理不了html中的img图片,只能处理css中的图片
  • 使用url-loader,需要下载file-loader,url依赖于file-loader
  • 图片大小小于8kb,就会被base64处理,
    优点:减少请求数量(减轻服务器压力),
    缺点:图片体积会更大(文件请求速度更慢)
  • base64在客户端本地解码所以会减少服务器压力,如果图片过大还采用base64编码会导致cpu调用率上升,网页加载时变卡
  • 问题:这里使用html-loader处理html文件的img图片时会出现一个问题,因为url-loader默认使用es6模块化解析,而html-loader引入图片是conmonjs,解析时会出问题:[object Module]
    解决:关闭url-loader的es6模块化,使用commonjs解析
  • 当webpack在解析的时候发现我们引入的是同一张图片,他不会重复打包,只会输入一次
 {
        // url-loader:处理图片资源,问题:默认处理不了html中的img图片
        test: /\.(jpg|png|gif)$/,
        // 需要下载 url-loader file-loader两个包
        loader: 'url-loader',//使用多个loader用use,使用一个loader用loader
        options: {
          limit: 8 \* 1024,
          // 给图片重命名,[hash:10]:取图片的hash的前10位,[ext]:取文件原来扩展名
          name: '[hash:10].[ext]',
          
          // 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是conmonjs,解析时会出问题:[object Module]
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule: false,
          outputPath: 'imgs'
			
        },
      },
      //当webpack在解析的时候发现我们引入的是同一张图片,他不会重复打包,只会输入一次
	   // 处理html文件的img图片
      {
        test: /\.html$/,
        // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
        loader: 'html-loader',//需要下载html-loader包 
      },

3.4 打包其他资源file-loader

url-loaderfile-loader的区别:

  • url-loader可以压缩图片,转换为base64
  • file-loader原封不动的将文件输出
      // 打包其他资源(除了html/js/css资源以外的资源) 比如字体图标
      {
        // 排除html|js|css|less|jpg|png|gif文件
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        // file-loader:处理其他文件
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media',
        },
      },

3.5 devServer 开发服务器

用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
特点:只会在内存中编译打包,不会有任何输出
需要下载包webpack-dev-server
启动derServer指令为: npx webpack-dev-server

devServer: {
  contentBase: resolve(__dirname, 'build'),//项目构建后路径
  compress: true,//启动gzip压缩
  port: 3000,//端口号
  open: true,//自动打开浏览器
  // 开启HMR功能
  // 当修改了webpack配置,新配置要想生效,必须重启webpack服务
  hot: true
}

下面是一个简单的开发环境webpack.confg.js配置文件
// resolve用来拼接绝对路径的方法
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引用plugin

module.exports = {
  // webpack配置
  entry: './src/js/index.js', // 入口起点
  output: {
    // 输出
    // 输出文件名
    filename: 'js/build.js',
    // \_\_dirname是nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'build'), // 输出路径,所有资源打包都会输出到这个文件夹下
  },
  // loader配置
  module: {
    rules: [
      // 详细的loader配置
      // 不同文件必须配置不同loader处理

      {
        // 匹配哪些文件
        test: /\.less$/,
        // 使用哪些loader进行处理
        use: [
          // use数组中loader执行顺序:从右到左,从下到上,依次执行(先执行css-loader)
          // style-loader:创建style标签,将js中的样式资源插入进去,添加到head中生效
          'style-loader',
          // css-loader:将css文件变成commonjs模块加载到js中,里面内容是样式字符串
          'css-loader',
          // less-loader:将less文件编译成css文件,需要下载less-loader和less
          'less-loader'
        ],
      },


      {
        test: /\.css$/,
        //使用多个loader用use,使用一个loader用loader
        use: ['style-loader', 'css-loader'],
      },



      {
        // url-loader:处理图片资源,问题:默认处理不了html中的img图片
        test: /\.(jpg|png|gif)$/,
        // 需要下载 url-loader file-loader两个包
        loader: 'url-loader',//使用多个loader用use,使用一个loader用loader
        options: {
          // 图片大小小于8kb,就会被base64处理,优点:减少请求数量(减轻服务器压力),缺点:图片体积会更大(文件请求速度更慢)
          // base64在客户端本地解码所以会减少服务器压力,如果图片过大还采用base64编码会导致cpu调用率上升,网页加载时变卡
          limit: 8 \* 1024,
          // 给图片重命名,[hash:10]:取图片的hash的前10位,[ext]:取文件原来扩展名
          name: '[hash:10].[ext]',
          // 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是conmonjs,解析时会出问题:[object Module]
          
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule: false,
          outputPath: 'imgs'//输出到imgs目录下
			
        },
      },
      //当webpack在解析的时候发现我们引入的是同一张图片,他不会重复打包,只会输入一次
	   // 处理html文件的img图片
      {
        test: /\.html$/,
        // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
        loader: 'html-loader',//需要下载html-loader包 
      },


	//url-loader和file-loader的区别:
	//url-loader可以压缩图片,转换为base64 
	//file-loader原封不动的将文件输入

      // 打包其他资源(除了html/js/css资源以外的资源) 比如字体图标
      {
        // 排除html|js|css|less|jpg|png|gif文件
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        // file-loader:处理其他文件
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media',
        },
      },
    ],
  },




  // plugin的配置
  plugins: [
    // html-webpack-plugin:默认会创建一个空的html文件,自动引入打包输出的所有资源(JS/CSS)
    // 需要有结构的HTML文件可以加一个template
    new HtmlWebpackPlugin({
      // 复制这个./src/index.html文件,并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html',
    }),
  ],



  // 模式
  mode: 'development', // 开发模式


  // 开发服务器 devServer:用来自动化,不用每次修改后都重新输入webpack打包一遍(自动编译,自动打开浏览器,自动刷新浏览器)
  // 特点:只会在内存中编译打包,不会有任何输出(不会像之前那样在外面看到打包输出的build包,而是在内存中,关闭后会自动删除)
  // 启动devServer指令为:npx webpack-dev-server
  devServer: {
    // 项目构建后路径
    contentBase: resolve(__dirname, 'build'),
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 3000,
    // 自动打开浏览器
    open: true,
  },
}

其中,大部分配置都在注释中给出解释。

  • 运行项目的两个指令:

webpack 会将打包结果输出出去(build文件夹)

npx webpack-dev-server 只会在内存中编译打包,没有输出

  • loader 和 plugin 的不同:(plugin 一定要先引入才能使用)

​ loader:1. 下载 2. 使用(配置 loader)

​ plugins:1.下载 2. 引入 3. 使用

四、Webpack 生产环境的基本配置

而生产环境的配置需要考虑以下几个方面:

1、提取 css 成单独文件mini-css-extract-plugin

css-loader:将css文件整合到js文件中,经过css-loader处理后,样式文件是在js文件中的

问题:1.js文件体积会很大 2.需要先加载js再动态创建style标签,样式渲染速度就慢,会出现闪屏现象

解决:用MiniCssExtractPlugin.loader替代style-loader,提取js中的css成单独文件然后通过link加载

const { resolve } = require('path')
const MiniCssExtractorPlugin = require('mini-css-extract-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use:[ 
            //'style-loader',//创建style标签,将样式放入
            //这个loader取代style-loader 作用:提取js中的css成单独文件
            MiniCssExtractorPlugin.loader,
            "css-loader"//将css文件整合到js文件中
        ],
      }
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'css/built.css',
    }),
   
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
  ],
  // 生产环境下会自动压缩js代码
  mode: 'production'
  
}

2、css 兼容性处理 postcss-loader

使用postcss-loader:css兼容性处理:postcss --> 需要安装:postcss-loader 和插件postcss-preset-env

有两种配置方法:

  • 使用loader的默认配置:postcss-loader ,这个在css-loader同级写postcss-loader
  • 修改loader的配置会使用到postcss-preset-env这个插件,它主要作用就是postcss会以这个插件的形式做一些兼容性处理
    在这里插入图片描述
    postcss需要通过package.jsonbrowserslist里面的配置加载指定的css兼容性样式

在这里插入图片描述
在package.json中定义browserslist


    "browserslist": {
      // 开发环境 --> 设置node环境变量:process.env.NODE\_ENV = development
      "development": [ // 只需要可以运行即可
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
      ],
      // 生产环境。默认是生产环境
      "production": [ // 需要满足绝大多数浏览器的兼容
        ">0.2%",
        "not dead",
        "not op\_mini all"
      ]
    },

默认是生产环境 , 这时候我们需要把nodejs环境变量设置为开发环境 , 开发环境主要是验证一些最近的浏览器的兼容性
在这里插入图片描述
这时候我们就可以看到打包的built.css里面的样式就会做一些兼容性处理了
在这里插入图片描述
如果我们将设置开发环境变量注释,那么我们会看到在生产环境端也是做了一些不同的兼容性处理
在这里插入图片描述

3、压缩 css optimizi-css-assets-webpack-plugin

安装optimizi-css-assets-webpack-plugin
压缩css非常简单,只需要配置一个插件即可

const OptimiziCssAssetsWebpackPlugin = require('optimizi-css-assets-webpack-plugin')
...
 plugins: [
    // 压缩css
    new OptimiziCssAssetsWebpackPlugin(),
  ],

4、js 语法检查eslint-loadereslint

js的语法检查: 需要下载 eslint-loadereslint

注意:只检查自己写的源代码,第三方的库是不用检查的

airbnb(一个流行的js风格) --> 需要下载 eslint-config-airbnb-base(这个库没有react的语法检查,如果需要react可用eslint-config-airbnb) 和eslinteslint-plugin-import

{
	test: /\.js$/,
	exclude: /node\_modules/, // 忽略node\_modules
	enforce: 'pre', // 优先执行
	loader: 'eslint-loader',
	options: {
	  // 自动修复
	  fix: true,
	},
},

设置检查规则: package.jsoneslintConfig中设置

"eslintConfig": {
   "extends": "airbnb-base", // 继承airbnb的风格规范
   "env": {
     "browser": true // 可以使用浏览器中的全局变量(使用window不会报错)
   }
 }

5、js 兼容性处理

js兼容性处理:需要下载 babel-loader 、·@babel/core@babel/preset-env@babel/polyfill

1. 基本js兼容性处理 --> @babel/preset-env

问题:只能转换基本语法,如promise高级语法不能转换

2. 全部js兼容性处理 --> @babel/polyfill(这个包不是插件,只需要引入就可以使用了)

问题:只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
在这里插入图片描述

3. 需要做兼容性处理的就做:按需加载 -->core-js

使用这种方案的话我们就不能使用第二种方案了

{
  // 第三种方式:按需加载
  test: /\.js$/,
  exclude: /node\_modules/,
  loader: 'babel-loader',
  options: {
    // 预设:指示babel做怎样的兼容性处理
    presets: [
      '@babel/preset-env', // 基本预设
      {
        useBuiltIns: 'usage', //按需加载
        corejs: { version: 3 }, // 指定core-js版本
        targets: { // 指定兼容到什么版本的浏览器
          chrome: '60',
          firefox: '50',
          ie: '9',
          safari: '10',
          edge: '17'
        },
      },
    ],
  },
},

6、js 压缩

生产环境会自动压缩js代码
在这里插入图片描述

7、html 压缩

html不需要做兼容性处理,只需要做压缩

 new HtmlWebpackPlugin({
   template: './src/index.html',
   // 压缩html代码
   minify: {
     // 移除空格
     collapseWhitespace: true,
     // 移除注释
     removeComments: true,
   },
 }),

下面是一个基本的生产环境下的webpack.config.js配置
  • 正常来讲,一个文件只能被一个loader处理,当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序 , 使用enforce优先执行
const { resolve } = require('path')
const MiniCssExtractorPlugin = require('mini-css-extract-plugin')
const OptimiziCssAssetsWebpackPlugin = require('optimizi-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 定义node.js的环境变量,决定使用browserslist的哪个环境
process.env.NODE\_ENV = 'production'

// 复用loader的写法
const commonCssLoader = [
  // 这个loader取代style-loader。作用:提取js中的css成单独文件然后通过link加载
  MiniCssExtractPlugin.loader,
  'css-loader',
  /\*postcss需要通过package.json中browserslist里面的配置加载指定的css兼容性样式
 在package.json中定义browserslist:见上面css兼容性处理的代码
 \*/
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss', // 基本写法
      plugins: () => [
        // postcss的插件
        require('postcss-preset-env')(),
      ],
    },
  },
]

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [...commonCssLoader],
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader'], //commonCssLoader一定要写到less-loader上面,因为它只能处理css文件,less-loader把less转换为css之后使用
      },
      /\*
 正常来讲,一个文件只能被一个loader处理
 当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序
 先执行eslint再执行babel(用enforce)
 \*/
      {
        //设置检查规则:` package.json`中`eslintConfig`中设置,见上面js语法检查设置规则
        test: /\.js$/,
        exclude: /node\_modules/, // 忽略node\_modules
        enforce: 'pre', // 优先执行
        loader: 'eslint-loader',
        options: {
          // 自动修复
          fix: true,
        },
      },
     
      {
        // js兼容性处理,第三种方式:按需加载
        test: /\.js$/,
        exclude: /node\_modules/,
        loader: 'babel-loader',
        options: {
          // 预设:指示babel做怎样的兼容性处理
          presets: [
            '@babel/preset-env', // 基本预设
            {
              useBuiltIns: 'usage', //按需加载
              corejs: { version: 3 }, // 指定core-js版本
              targets: { // 指定兼容到什么版本的浏览器
                chrome: '60',
                firefox: '50',
                ie: '9',
                safari: '10',
                edge: '17'
              },
            },
          ],
        },
      },
      {
        // 图片处理
        test: /\.(jpg|png|gif)/,
        loader: 'url-loader',
        options: {
          limit: 8 \* 1024,
          name: '[hash:10].[ext]',
          outputPath: 'imgs',
          esModule: false, // 关闭url-loader默认使用的es6模块化解析
        },
      },
      // html中的图片处理
      {
        test: /\.html$/,
        loader: 'html-loader',
      },
      // 处理其他文件
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          outputPath: 'media',
        },
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'css/built.css',
    }),
    // 压缩css
    new OptimiziCssAssetsWebpackPlugin(),
    // HtmlWebpackPlugin:html文件的打包和压缩处理
    // 通过这个插件会自动将单独打包的样式文件通过link标签引入
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // 压缩html代码
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
      },
    }),
  ],
  // 生产环境下会自动压缩js代码
  mode: 'production',
  devServer: {
  contentBase: resolve(__dirname, 'build'),
  compress: true,
  port: 3000,
  open: true,
  // 开启HMR功能
  // 当修改了webpack配置,新配置要想生效,必须重启webpack服务
  hot: true
}
}

五、Webpack 优化配置

5.1 开发环境性能优化

开发环境指令通过npx webpack-dev-server启动,如果直接运行webpack是会直接打包,看不到实时调试的效果

5.1.1 HMR(模块热替换) 优化打包构建速度

HMR: hot module replacement 热模块替换 / 模块热替换,基于devServer,只能在开发环境使用

作用:一个模块发生变化,只会重新打包构建这一个模块(而不是打包所有模块) ,极大提升构建速度

代码:只需要在 devServer 中设置 hottrue,就会自动开启HMR功能(只能在开发模式下使用)

devServer: {
  contentBase: resolve(__dirname, 'build'),
  compress: true,
  port: 3000,
  open: true,
  // 开启HMR功能
  // 当修改了webpack配置,新配置要想生效,必须重启webpack服务
  hot: true
}

每种文件实现热模块替换的情况:

  • 样式文件:可以使用HMR功能,因为开发环境下使用的style-loader 内部默认实现了热模块替换功能
  • js 文件:默认不能使用HMR功能(修改一个 js 模块所有 js 模块都会刷新)

解决:实现 HMR 需要修改 js 代码(添加支持 HMR 功能的代码)

注意:

1. HMR 功能对 js 的处理,只能处理非入口 js 文件的其他文件,因为入口文件会将其他文件引入,一旦入口文件变化,其他文件又会重新引入重新加载,所以入口文件做不了HMR功能
2. 如果有多个js文件,则需要写多个这样的函数
```
// 绑定
if (module.hot) {
  // 一旦 module.hot 为true,说明开启了HMR功能。 --> 让HMR功能代码生效
  module.hot.accept('./print.js', function() {
    // 方法会监听 print.js 文件的变化,一旦发生变化,只有这个模块会重新打包构建,其他模块不会。
    // 会执行后面的回调函数
    print();
  });
}

```
  • html 文件: 默认不能使用 HMR 功能,同时会导致问题:html文件不能热更新了,不会自动打包构建(html 不用做 HMR 功能,如果是针对单文件组件的话,因为只有一个 html 文件,不需要再优化)

解决:修改 entry 入口,将 html 文件引入(这样 html 修改,整体又会重新刷新)

entry: ['./src/js/index.js', './src/index.html']

5.1.2 source-map 优化代码调式

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

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

代码:

devServer: {
  ...
},
devtool: 'source-map'

可选方案:[生成source-map的位置|给出的错误代码信息]

  1. source-map:外部,错误代码准确信息 和 源代码的错误位置
  2. inline-source-map:内联,只生成一个内联 source-map,错误代码准确信息 和 源代码的错误位置
  3. hidden-source-map:外部,错误代码错误原因,但是没有错误位置(为了隐藏源代码),不能追踪源代码错误,只能提示到构建后代码的错误位置
  4. eval-source-map:内联,每一个文件都生成对应的 source-map,都在 eval 中,错误代码准确信息 和 源代码的错误位
  5. nosources-source-map:外部,错误代码准确信息,但是没有任何源代码信息(为了隐藏源代码)
  6. cheap-source-map:外部,错误代码准确信息 和 源代码的错误位置,只能把错误精确到整行,忽略列
  7. cheap-module-source-map:外部,错误代码准确信息 和 源代码的错误位置,module 会加入 loader 的 source-map

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

开发/生产环境可做的选择:

开发环境:需要考虑速度快,调试更友好

  • 速度快( eval > inline > cheap >… )
    eval-cheap-souce-map
    eval-source-map
  • 调试更友好
    souce-map
    cheap-module-souce-map
    cheap-souce-map

最终得出最好的两种方案 --> eval-source-map(完整度高,内联速度快 ,vue和react脚手架默认配置的就是这个) / eval-cheap-module-souce-map(错误提示忽略列但是包含其他信息,内联速度快)

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

  • 内联会让代码体积变大,所以在生产环境不用内联
  • 隐藏源代码
    nosources-source-map 全部隐藏
    hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
    最终得出最 好的两种方案 --> source-map(最完整) / cheap-module-souce-map(错误提示一整行忽略列)

5.2 生产环境性能优化

5.2.1 优化打包构建速度
1、 oneOf 匹配到 loader 后就不再向后进行匹配

oneOf:匹配到 loader 后就不再向后进行匹配,优化生产环境的打包构建速度

  • 以下loader只会匹配一个(匹配到了后就不会再往下匹配了)
  • 注意:不能有两个配置处理同一种类型文件(所以把eslint-loader提取出去放外面)
module: {
  rules: [
    {
      // js 语法检查
      test: /\.js$/,
      exclude: /node\_modules/,
      // 优先执行
      enforce: 'pre',
      loader: 'eslint-loader',
      options: {
        fix: true
      }
    },
    {
      // oneOf 优化生产环境的打包构建速度
      // 以下loader只会匹配一个(匹配到了后就不会再往下匹配了)
      // 注意:不能有两个配置处理同一种类型文件(所以把eslint-loader提取出去放外面)
      oneOf: [
        {
          test: /\.css$/,
          use: [...commonCssLoader]
        },
        {
          test: /\.less$/,
          use: [...commonCssLoader, '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,
            name: '[hash:10].[ext]',
            outputPath: 'imgs',
            esModule: false
          }
        },
        {
          test: /\.html$/,
          loader: 'html-loader'
        },
        {
          exclude: /\.(js|css|less|html|jpg|png|gif)/,
          loader: 'file-loader',
          options: {
            outputPath: 'media'
          }
        }
      ]
    }
  ]
},

2、 babel 缓存: cacheDirectory

类似 HMR,将 babel 处理后的资源缓存起来(哪里的js改变就更新哪里,其他 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
  }
},

3 、多进程打包 thread-loader

多进程打包:某个任务消耗时间较长会卡顿,多进程可以同一时间干多件事,效率更高。

优点是提升打包速度,缺点是每个进程的开启和交流都会有开销(babel-loader消耗时间最久,所以使用thread-loader 针对其进行优化)

{
  test: /\.js$/,
  exclude: /node\_modules/,
  use: [
    /\* 
 thread-loader会对其后面的loader(这里是babel-loader)开启多进程打包。 
 进程启动大概为600ms,进程通信也有开销。(启动的开销比较昂贵,不要滥用)
 只有工作消耗时间比较长,才需要多进程打包
 \*/
    {
      loader: 'thread-loader',
      options: {
        workers: 2 // 进程2个
      }
    }, 
    {
      loader: 'babel-loader',
      options: {
        presets: [
          [
            '@babel/preset-env',
            {
              useBuiltIns: 'usage',
              corejs: { version: 3 },
              targets: {
                chrome: '60',
                firefox: '50'
              }
            }
          ]
        ],
        // 开启babel缓存
        // 第二次构建时,会读取之前的缓存
        cacheDirectory: true
      }
    }
  ]
},


4 、externals , 让某些库不打包

externals:让某些库不打包,通过 cdn 引入

webpack.config.js 中配置:

externals: {
  // 拒绝jQuery被打包进来(通过cdn引入,速度会快一些)
  // 忽略的库名 -- npm包名
  jquery: 'jQuery'
}

需要在 index.html 中通过 cdn 引入:

<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>

5 、dll 让某些库单独打包

dll:让某些库单独打包后直接引入到 build 中,优化了重复打包的性能
可以在 code split 分割出 node_modules 后再用 dll 更细的分割,优化代码运行的性能。

  • node_modules的库会打包到一起,但是很多库的时候打包输出的js文件就太大了
  • 使用dll技术,对某些库(第三方库:jquery、react、vue…)进行单独打包
  • 当运行webpack时,默认查找webpack.config.js配置文件
  • 而我们通过dll打包之后需要运行webpack.dll.js文件,这时候我们就需要修改webpack的指令 --> webpack --config webpack.dll.js(运行这个指令表示以这个配置文件打包)

webpack.dll.js 配置:(将 jquery 单独打包)


const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    // 最终打包生成的[name] --> jquery
    // ['jquery] --> 要打包的库是jquery
    jquery: ['jquery']//这里可以写很多很多库,可以分别打包
  },
  output: {
    // 输出出口指定
    filename: '[name].js', // name就是jquery
    path: resolve(__dirname, 'dll'), // 打包到dll目录下
    library: '[name]\_[hash]', // 打包的库里面向外暴露出去的内容叫什么名字
  },
  plugins: [
    // 打包生成一个manifest.json --> 提供jquery的映射关系(告诉webpack:jquery之后不需要再打包和暴露内容的名称)
    new webpack.DllPlugin({
      name: '[name]\_[hash]', // 映射库的暴露的内容名称
      path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
    })
  ],
  mode: 'production'
};

webpack.config.js 配置:(告诉 webpack 不需要再打包 jquery,并将之前打包好的 jquery 跟其他打包好的资源一同输出到 build 目录下)

// 引入插件
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

// plugins中配置:
plugins: [
  new HtmlWebpackPlugin({
    template: './src/index.html'
  }),
  // 告诉webpack哪些库不参与打包,同时使用时的名称也得变
  new webpack.DllReferencePlugin({
    manifest: resolve(__dirname, 'dll/manifest.json')
  }),
  // 将某个文件打包输出到build目录下,并在html中自动引入该资源
  new AddAssetHtmlWebpackPlugin({
    filepath: resolve(__dirname, 'dll/jquery.js')
  })
],

externals和dll的区别
  • externals彻底不打包,需要通过cdn连接引进来
  • dll需要打包一次,不用重复打包,可以结合代码分割,按需拆分文件
5.2.2 优化代码运行的性能
1、文件资源缓存 hash->chunkhash->contenthash

文件名不变,就不会重新请求,而是再次用之前缓存的资源

  1. hash: 每次 wepack 打包时会生成一个唯一的 hash 值。

问题:重新打包,所有文件的 hash 值都改变,会导致所有缓存失效。(比如只改动了一个js文件,css文件也会被重新打包)
原因:因为js和css同时使用一个hash值
2. chunkhash:根据 chunk 生成的 hash 值。来源于同一个 chunk的 hash 值一样

问题:js 和 css 来自同一个chunk,hash 值是一样的
原因:因为 css-loader 会将 css 文件加载到 js 中,所以同属于一个chunk

chunk概念:比如一个入口文件引入了css文件、js文件,形成了一个文件 ,这个文件就叫做一个chunk
3. contenthash: 根据文件的内容生成 hash 值。不同文件 hash 值一定不一样(文件内容修改,文件名里的 hash 才会改变)

修改 css 文件内容,打包后的 css 文件名 hash 值就改变,而 js 文件没有改变 hash 值就不变,这样 css 和 js 缓存就会分开判断要不要重新请求资源 --> 让代码上线运行缓存更好使用
在这里插入图片描述
打包结果:不同文件hash值都不一样,再次打包,只要文件内容不变,hash值就不会变化
在这里插入图片描述

2、tree shaking 去除无用代码

前提:

  1. 必须使用 ES6 模块化
  2. 开启 production 环境 (这样就自动会把无用代码去掉)

作用:减少代码体积

在一些webpack版本中,可能会摇掉一些css等的代码,这时候我们需要在 package.json 中配置:

"sideEffects": false 表示所有代码都没有副作用(都可以进行 tree shaking),这样会导致的问题:可能会把 css / @babel/polyfill 文件干掉(副作用)

所以可以配置:"sideEffects": ["*.css", "*.less"] 不会对css/less文件tree shaking处理

3、 code split(代码分割)

代码分割主要有两种场景:单入口场景和多入口场景。

将打包输出的一个大的 bundle.js 文件拆分成多个小文件,这样可以并行加载多个文件,比加载一个文件更快。

比如我们在开发单页面应用的时候,如vue,整个页面是一个非常庞大的文件,那么我们肯定要按照路由去拆分不同的文件,从而实现按需加载,这时候拆分文件就需要使用代码分割了

1)多入口拆分

多入口:有几个入口,最终输出就有几个bundle
问题:很难去维护多入口,如果要修改多个页面总得去修改多入口

entry: {
    // 多入口:有几个入口,最终输出就有几个bundle
    index: './src/js/index.js',
    test: './src/js/test.js'
  },
  output: {
    // [name]:取文件名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },

2)optimization: 将 node_modules中的代码单独打包
  • node_modules中的代码单独打包(大小超过30kb)
  • 自动分析多入口chunk中,有没有公共的文件。如果有会打包成单独一个chunk(比如两个模块中都引入了jquery,正常情况下多入口页面会打包两个引入jquery的文件,使用optimization会被打包成一个单独的文件,不会重复打包多次)(大小超过30kb)
optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },

3)import 动态导入语法:
  • 通过js代码,让某个文件被单独打包成一个chunk,采用id命名(0、1、2、3…),避免命名冲突
  • import动态导入语法:能将某个文件单独打包(test文件不会和index打包在同一个文件而是单独打包)
  • webpackChunkName:指定test单独打包后文件的名字

import(/\* webpackChunkName: 'test' \*/'./test')
  .then(({ mul, count }) => {
    // 文件加载成功~
    // eslint-disable-next-line
    console.log(mul(2, 5));
  })
  .catch(() => {
    // eslint-disable-next-line
    console.log('文件加载失败~');
  });

4、 lazy loading(懒加载/预加载)
  1. 懒加载:当文件需要使用时才加载(需要代码分割)。但是如果资源较大,加载时间就会较长,有延迟。
  2. 正常加载:可以认为是并行加载(同一时间加载多个文件)没有先后顺序,先加载了不需要的资源就会浪费时间。
  3. 预加载 prefetch(兼容性很差):会在使用之前,提前加载。等其他资源加载完毕,浏览器空闲了,再偷偷加载这个资源。这样在使用时已经加载好了,速度很快。所以在懒加载的基础上加上预加载会更好。

代码:

document.getElementById('btn').onclick = function() {
  // 将import的内容放在异步回调函数中使用,点击按钮,test.js才会被加载(不会重复加载)
  // webpackPrefetch: true表示开启预加载
  import(/\* webpackChunkName: 'test', webpackPrefetch: true \*/'./test').then(({ mul }) => {
    console.log(mul(4, 5));
  });
  import('./test').then(({ mul }) => {
    console.log(mul(2, 5))
  })
};

5、pwa(离线可访问技术)

pwa:离线可访问技术(渐进式网络开发应用程序),使用serviceworkerworkbox 技术。

优点是离线也能访问,缺点是兼容性差。

webpack.config.js 中配置:

const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); // 引入插件

// plugins中加入:
new WorkboxWebpackPlugin.GenerateSW({
  /\*
 1. 帮助serviceworker快速启动
 2. 删除旧的 serviceworker

 生成一个 serviceworker 配置文件
 \*/
  clientsClaim: true,
  skipWaiting: true
})

index.js 中还需要写一段代码来激活它的使用:


if ('serviceWorker' in navigator) { // 处理兼容性问题
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js') // 注册serviceWorker
      .then(() => {
        console.log('sw注册成功了~');
      })
      .catch(() => {
        console.log('sw注册失败了~');
      });
  });
}

  1. eslint不认识 window、navigator全局变量
    解决:需要修改package.json中eslintConfig配置

 
    "env": {
      "browser": true // 支持浏览器端全局变量
    }



  1. sw代码必须运行在服务器上
    –> nodejs
    或–>npm i serve -g (serve这个包可以快速帮我们添加一个静态资源服务器)
    serve -s build 启动服务器,将打包输出的build目录下所有资源作为静态资源暴露出去

六、Webpack 配置详情

6.1 entry

entry: 入口起点

  1. string --> './src/index.js',单入口

打包形成一个 chunk。 输出一个 bundle 文件。此时 chunk 的名称默认是main
2. array --> ['./src/index.js', './src/add.js'],多入口

所有入口文件最终只会形成一个 chunk,输出出去只有一个 bundle 文件main.js

(一般只用在 HMR 功能中让 html 热更新生效)
3. object -->{ index : './src/index.js', add : './src/add.js' },多入口

有几个入口文件就形成几个 chunk,输出几个 bundle 文件,此时 chunk 的名称是 key 值
4. –> 特殊用法:

总结一下

面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。

还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1847294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

艺术创作加速器:三款AI绘画软件,让你的工作效率倍增!

在数字化浪潮的推动下&#xff0c;艺术创作正迎来革命性的变化。AI绘画软件的出现&#xff0c;不仅为艺术家提供了全新的创作工具&#xff0c;也为艺术爱好者开辟了一片创意的新天地。这些软件利用人工智能技术&#xff0c;根据用户的简单描述或草图&#xff0c;快速生成独特的…

Vector 例题

例题一&#xff1a; 下面这个代码输出的是( ) &#xfeff;#include <iostream> #include <vector> using namespace std; int main(void) { vector<int>array; array.push_back(100); array.push_back(300); array.push_back(300); array.push_back(300); a…

探索图神经网络(GNN):使用Python实现你的GNN模型

一、引言 图神经网络&#xff08;Graph Neural Network, GNN&#xff09;作为近年来机器学习和深度学习领域的热门话题&#xff0c;正逐渐吸引越来越多的研究者和开发者的关注。GNN能够处理图结构数据&#xff0c;在社交网络分析、推荐系统、化学分子结构预测等领域有着广泛的…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 任务安排问题(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 https://app5938.acapp.acwing.com.cn/contest/2/problem/OD…

课程管理系统

摘 要 在大学里&#xff0c;课程管理是一件非常重要的工作&#xff0c;教学工作人员每天都要与海量的数据和信息打交道。确保数据的精确度和完整程度&#xff0c;影响着每一位同学的学习、生活和各种活动的正常展开&#xff0c;更合理的信息管理也为高校工作的正规化运行和规范…

ThinkPHP6图书借阅管理系统

有需要请加文章底部Q哦 可远程调试 ThinkPHP6图书借阅管理系统 一 介绍 此图书借阅管理系统基于ThinkPHP6框架开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 ThinkPHP6mysqlbootstrapphpstudyvscode 二 功能 用户 1 登录/注销…

Vitis Accelerated Libraries 学习笔记--Vision 库介绍

目录 1. 简介 2. 分类介绍 2.1 图像容器 2.2 图像处理基础 2.3 图像滤波和平滑 2.4 图像变换和增强 2.5 图像分析和特征检测 2.6 数学和算术操作 2.7 图像校正和优化 2.8 颜色和阈值处理 2.9 高级图像处理 2.10 光流和运动估计 2.11 图像转换和映射 2.12 其他特殊…

【服务器05】之【登录/注册账号成功转至游戏场景】

Unity登录注册数据库 打开【服务器01】的文章项目 导入新UI系统 点击2D 双击输入栏位置 修改输入框尺寸及位置 放大字体 修改默认输入文字 发现中文字变成了口口口口 原因是新UI系统不支持中文&#xff0c;解决这个问题需要更换字体 并且修改输入时字体大小 我们取电脑中找Fon…

【ARMv8/v9 GIC 系列 4.3 -- GIC 中断控制系统寄存器 ICC_SRE_ELn 使用介绍】

文章目录 GIC 中断控制系统寄存器 ICC_SRE_ELn寄存器位域介绍Interrupt BypassBypass IRQBypass FIQBypass 配置GIC 中断控制系统寄存器 ICC_SRE_ELn ICC_SRE_EL3是中断控制器系统寄存器(Interrupt Controller System Register),用于控制在异常级别3(EL3)下,对GIC CPU接口…

Hive基础教程

文章目录 Apache Hive 教程1. Hive-简介1.1 学习Hive的前置知识1.2 什么是Hive&#xff1f;1.3 Hive的架构1.4 Hive的工作流程 Apache Hive 教程 资料来源&#xff1a;Hive Tutorial (tutorialspoint.com) Hive是Hadoop中用于处理结构化数据的数据仓库基础设施工具。它驻留在H…

pywinauto入门指南:轻松掌握Windows GUI自动化

pywinauto库概述: pywinauto是一个Python库,主要用于自动化Windows应用程序的GUI测试和操作.它提供了一组简单而强大的API,可以模拟用户与Windows应用程序的交互,包括点击按钮、输入文本、选择菜单等操作. 安装 ##pywinauto可以通过pip进行安装,打开命令行运行: pip install…

AI落地不容乐观-从神话到现实

开篇 在这儿我不是给大家泼冷水&#xff0c;而是我们一起来看一下从2022年11月左右GPT3.0掀起了一股“AI狂潮”后到现在&#xff0c;AI在商用、工业、军用下到底有没有得到了大规模应用呢&#xff1f; 这个答案每一个参与者其实心里有数那就是&#xff1a;没有。 但是呢它的…

STM32学习和实践笔记(36):DAC数模转换实验

1.STM32F1 DAC简介 DAC&#xff08;Digital to analog converter&#xff09;即数字模拟转换器&#xff0c;它可以将数字信号转换为模拟信号。它的功能与ADC相反。在常见的数字信号系统中&#xff0c;大部分传感器信号被转化成电压信号&#xff0c;而 ADC 把电压模拟信号转换成…

算法设计与分析:分治法求最近点对问题

一、实验目的 1. 掌握分治法思想&#xff1b; 2. 学会最近点对问题求解方法。 二、实验内容 1. 对于平面上给定的N个点&#xff0c;给出所有点对的最短距离&#xff0c;即&#xff0c;输入是平面上的N个点&#xff0c;输出是N点中具有最短距离的两点。 2. 要求随机生成N个…

项目训练营第三天

项目训练营第三天 注册登录测试 前面我们编写了用户注册、登录的逻辑代码&#xff0c;每编写完一个功能模块之后&#xff0c;我们都要对该模块进行单元测试&#xff0c;来确保该功能模块的正确性。一般情况下使用快捷键Ctrl Shift Insert&#xff0c;鼠标左击类名可以自动生…

灵活的招聘管理系统有五种方法帮助成功招聘

还记得以前的时代吗&#xff1f;这取决于你的年龄&#xff0c;直到智能手机、流媒体电视和电子邮件出现。今天&#xff0c;任何活着的成年人都经历了技术上的巨大变化&#xff0c;这创造了一种新的行为方式。人才获取也是如此。 一个值得推荐的招聘管理系统 招聘团队被困在满足…

机器人系统工具箱的 Gazebo 模拟

Gazebo 联合仿真模块 机器人系统工具箱> Gazebo联合仿真模块库包含与仿真环境相关的 Simulink 模块。要查看该库&#xff0c;在 MATLAB 命令提示符下输入robotgazebolib。

AIGC-CVPR2024best paper-Rich Human Feedback for Text-to-Image Generation-论文精读

Rich Human Feedback for Text-to-Image Generation斩获CVPR2024最佳论文&#xff01;受大模型中的RLHF技术启发&#xff0c;团队用人类反馈来改进Stable Diffusion等文生图模型。这项研究来自UCSD、谷歌等。 在本文中&#xff0c;作者通过标记不可信或与文本不对齐的图像区域&…

机器学习(V)--无监督学习(六)流形学习

title: 机器学习(V)–无监督学习(二)流形学习 date: katex: true categories: Artificial IntelligenceMachine Learning tags:机器学习 cover: /img/ML-unsupervised-learning.png top_img: /img/artificial-intelligence.jpg abbrlink: 26cd5aa6 description: 流形学习 【降…

String(C++)

文章目录 前言文档介绍经典题目讲解HJ1 字符串最后一个单词的长度 模拟实现框架构造函数析构函数迭代器c_str()赋值size()capacity()reserveempty()[ ]访问front/backpush_backappendoperatorinsert一个字符insert一个字符串eraseswapfind一个字符find一个字符串substr()clear(…