【Webpack学习笔记】二、生产环境下的使用

【Webpack学习笔记】二、生产环境下的使用

参考课程:尚硅谷最新版Webpack5实战教程(从入门到精通)哔哩哔哩bilibili

更新:2021年10月17日02:06:37

参考:【Webpack学习笔记】一、基本使用_赖念安的博客-优快云博客

在之前的【【Webpack学习笔记】一、基本使用】中,我们都是在开发环境下(mode 值为 development)对Webpack进行相关配置,接下来我们将逐渐了解在生产环境下如何配置Webpack。

相较于开发环境,生产环境中的输出结果体积相对更小,运行时也更快且更加平稳,经过我们的相关配置,其兼容性等方面的表现也会更好。

一、对CSS的处理

1、将CSS提取为单独的文件

此前在【【Webpack学习笔记】一、基本使用】中,我们处理CSS样式代码时都是借助 css-loader 来将样式代码直接作为一个模块(以样式字符串的形式)加载到作为Webpack打包输出结果的 built.js 文件中。然后再通过 style-loader 创建一个 <style> 标签并将js文件中的样式代码放在标签内,最后将标签插入html网页中。这样就可能会导致闪屏等问题。所以要将CSS样式代码提取为单独的 .css 文件。

要达到这个目标,我们需要借助 mini-css-extract-plugin 这个插件。

首先还是本地安装:

$ npm i mini-css-extract-plugin -D

然后是在 webpack.config.js 中配置:

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = 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标签,将样式放入
          // 'style-loader', 
          // 这个loader将取代style-loader。作用:提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    // 如果不给构造函数传入配置对象参数,则会默认在build目录下输出一个main.css样式文件
    // new MiniCssExtractPlugin()
    new MiniCssExtractPlugin({
      // 可以通过配置对象中filename属性来对输出的css文件进行重命名和目录整理
      filename: 'css/built.css'
    })
  ],
  // 这里的打包模式暂时还保持为开发模式
  mode: 'development'
};

注意,配置该插件的同时也要在 module 中配置相应的loader:MiniCssExtractPlugin.loader,该loader的作用就是将原本写入到 built.js 中的字符串格式的样式代码抽取出来放到一个单独的 .css 文件中,然后在输出的html文件中通过 <link> 标签的形式来引入生成的css文件。因为不再通过插入 <style> 标签的形式来引入样式,所以就不再需要 style-loader 了。

2、CSS兼容性处理

在通过CSS设置网页元素样式时,各个浏览器的兼容性是一个比较需要注意的问题,这也是前端开发比较难处理的地方。我们可以在webpack中通过 postcss-loader(loader)和 postcss-preset-env (plugin)来完成兼容性处理。 postcss-preset-env 可以根据具体的浏览器版本来做兼容处理。

使用前先通过 npm 下载这两个模块:

$ npm i postcss-loader postcss-preset-env -D

然后在 webpack.config.js 中配置相应loader:

// webpack.config.js

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

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          // 注意上面这种写法会使用loader的默认配置,
          // 而以下面这种对象的形式指明loader则可以通过options选项来自定义某些配置
          {
            // 指明loader名称
            loader: 'postcss-loader',
            // 设置自定义的配置选项
            options: {
              // ident是固定写法
              ident: 'postcss',
              // plugins是指明该loader所用到的插件,注意其值为函数,且返回值是一个数组
              plugins: () => [
                // 引入需要用到的插件,注意引入的结果是一个构造函数
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    ...
  ],
  // 这里的打包模式暂时还保持为开发模式
  mode: 'development'
};

postcss-preset-env 插件的作用是帮助 postcss 找到 package.json 中的 browserlist 配置项:

// 项目根目录下的 package.json 文件

{
  "name": "webpack_code",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {...},
  "devDependencies": {...},
  "dependencies": {...},
  "browserslist": {
    // 项目运行时如果设置为开发环境,则加载development中的配置
    // 开发时的要求不是那么严格,只要兼容一些主流浏览器的最新版本已完成调试工作就可以了
    "development": [
      // 兼容Chrome最近的一个版本
      "last 1 chrome version",
      // 兼容Firefox最近的一个版本
      "last 1 firefox version",
      // 兼容Safari最近的一个版本
      "last 1 safari version"
    ],
    // 项目运行时如果设置为生产环境,则加载production中的配置(默认情况读取该配置)
    // 生产环境的要求就高一点了,需要考虑实际运行时可能会出现的兼容问题
    "production": [
      // 兼容0.2%以上的浏览器
      ">0.2%",
      // 不兼容已经消亡的浏览器
      "not dead",
      // 不兼容所有op_mini浏览器
      "not op_mini all"
    ]
  }
}

有关 browserlist 的相关配置可以在GitHub上搜索符合要求的配置。也可以参看以下的博客:

更新:2021年10月16日20:59:07

参考:browserslist/browserslist-example: What tools and how uses Browserslist

参考:前端工程基础知识点–Browserslist (基于官方文档翻译) - 掘金

参考:browserslist使用手册 - 简书

注意上面 package.json 中所说的 development(开发环境)和 production (生产环境)与 webpack.config.js 中的 mode 配置没有什么关系,而是指项目运行时的一个临时环境,如果需要设置当前运行环境为开发环境的话,可以在 webpack.config.js 中通过 process.env.NODE_ENV 这一变量来对Node.js环境做如下设置:

// webpack.config.js

// 设置Node.js环境变量为development
process.env.NODE_ENV = 'development';

module.exports = {
  ...
  // 这里的打包模式暂时还保持为开发模式
  mode: 'development'
};

兼容性处理的效果如下:

/* 处理前的样式设置 a.css */

#box1 {
  width: 100px;
  height: 100px;
  /* 上面两个属性不需要做兼容性处理,而下面两个属性就需要了,注意观察处理前后的变化 */
  display: flex;
  backface-visibility: hidden;
}

经过 postcsspostcss-preset-env 处理后的相关代码:

/* 处理后的样式设置 built.css */

#box1 {
  width: 100px;
  height: 100px;
  /* 上面两个属性没有改变,而下面两个属性经过兼容性处理后就发生了变化 */
  display: -webkit-box;
  display: flex;
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
}

3、压缩CSS

实际开发中,在发布项目之前一定要对代码进行压缩,这样就可以减少请求时间,提升用户体验。而在webpack中压缩CSS是通过 optimize-css-assets-webpack-plugin 这个插件来完成的。

这个插件的功能就是将项目中的CSS代码压缩为一行,从而达到减小体积的效果。使用步骤和此前讲到的 html-webpack-plugin 是一样的。

同样地,在使用该插件前需要通过 npm 下载:

$ npm i optimize-css-assets-webpack-plugin -D

然后是在 webpack.config.js 中配置:

// webpack.config.js

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

// 和其他插件一样,在使用该插件前需要通过require语句引入,引入结果是一个构造函数
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    // 重复的配置就不展示了
    ...
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
    // 在plugins中配置插件,其实就是调用一下上面引入的构造函数来压缩css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  mode: 'development'
};

二、对JS的处理

1、JS语法检查

有时,开发者写的代码可以正确运行,但是其书写规范和格式等代码风格方面的问题却不利于团队之间的协作和后期维护,所以需要在一定规则下进行代码书写,而 eslint 就是专门做这个代码检查的工作的。

我们使用 eslint-loader 这个loader来进行代码检查,而这个loader依赖于 eslint 这个模块,所以在使用前需要下载这两个模块:

$ npm eslint eslint-loader -D
1.1、eslint-config-airbnb-base

上面说了进行代码检查是需要遵循一定规则的,而这个规则需要我们在配置 eslint-loader 时指定。一般我们是指定规则为 airbnb,而要使得该规则在 eslint 中生效的话,就需要事先下载 eslint-config-airbnb-base 这个模块,而这个模块又依赖于 eslint (上面下载了就可以不用重复下载了)和 eslint-plugin-import 这两个模块,所以这两个模块也要事先下载好:

# 因为上面已经下载过eslint,所以我这里就不重复下载它了
$ npm i eslint-config-airbnb-base eslint-plugin-import -D

有关 eslint-config-airbnb-base 的介绍可以看下方的链接:

参考:eslint-config-airbnb-base - npm

参考:eslint-config-airbnb - npm

注意:eslint-config-airbnb-base 和 eslint-config-airbnb 的区别就在于后者多了有关 React 的语法检查规则。

有关 airbnb 规则的介绍可以看其GitHub官网:

参考:airbnb/javascript: JavaScript Style Guide

1.2、配置 package.json 中的 eslintConfig

在完成前面的准备工作后,就需要在项目根目录下的 package.json 增加一个 eslintConfig 配置项了:

// 项目根目录下的 package.json 文件

{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {...},
  "devDependencies": {...},
  "dependencies": {...},
  "browserslist": {...},
  // 配置eslintConfig                   
  "eslintConfig": {
    // 使用extends属性来让eslint继承airbnb-base的js语法检查规则
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  }
}

然后是在 webpack.config.js 中配置相应loader:

// webpack.config.js

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

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        // 注意,检查时应当排除第三方库中的js文件(即node_modules目录下的文件),
        // 因为这些文件都发布前都已经检查过了,我们没必要重复检查,那样很费时间,
        // 所以只需要检查自己写的js源代码文件,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // 开启eslint检查可能会在打包时出现许多报错或者警告,我们可以根据这些提示信息
          // 手动对相应位置的代码进行修改,设置fix为true则会在检查时自动对报错的代码进行修改
          // 自动修复eslint的错误
          fix: true
        }
      }
    ]
  },
  plugins: [
    ...
  ],
  mode: 'development'
};

注意,如果想要 eslint 检查时,忽略某一行语句,则可以在该语句的前一行写该注释:// eslint-disable-next-line,意为让 eslint 在检查下一行时忽略所有检查规则。

// xxx.js
...
console.log(xxx);

在生成环境中往往不会进行控制台输出,所以在进行eslint检查时,上面的 console.log 语句会有警告:

...\src\js\index.js
  7:1  warning  Unexpected console statement  no-console

✖ 1 problem (0 errors, 1 warning)
...

加上注释后就可以让警告消失:

// xxx.js
...
// eslint-disable-next-line
console.log(xxx);

2、JS兼容性处理

各个浏览器对JavaScript的语言标准的支持各有不同,有些语法在Chrome中能够正常运行,但是到了IE之类的浏览器中却会报错,有些高级语法也是这样的情况。所以需要对JavaScript的语法做兼容性处理。

对js做兼容性处理时需要在 module 中配置一个loader:babel-loader。而该loader需要依赖于 @babel/core 这个模块,所以需要事先下载这两个模块:

$ npm i babel-loader @babel/core -D

然后就是在 webpack.config.jsmodule 中配置相应的loader。

1.1、基本语法的兼容

如果只需要对基本的JavaScript语法做兼容,那么就可以使用 @babel-preset-env 这个模块,在使用前需要安装该模块:

$ npm i @babel-preset-env -D

配置 webpack.config.jsmodule

// webpack.config.js

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        // 同样地,做兼容性处理时应当排除第三方库中的js文件
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
        	// preset是预设的意思,该属性指示babel-loader对js文件做怎样的兼容性转化处理
          // 而在@babel-preset-env中就有一些对js基础语法的兼容性转化规则
        	preset: ['@babel-preset-env']
        }
      }
    ]      
  },
  plugins: [
    ...
  ],
  mode: 'development'
};

兼容性处理前:

// .src/js/index.js

const add = (x, y) => {
  return x + y;
};
console.log(add(2, 5));

兼容性处理后:

// .build/js/built.js
...
/***/ "./src/js/index.js":
/*!*************************!*\
  !*** ./src/js/index.js ***!
  \*************************/
/*! no static exports found */
/***/ (function (module, exports) {
eval("var add = function add(x, y) {\n  return x + y;\n};\n\nconsole.log(add(2, 5)); //# sourceURL=webpack:///./src/js/index.js?");
})

可以看到,babel-loader 将原本的箭头函数写法改为了普通函数写法,且将ES6中的 const 关键字改为了 var 关键字。

1.2、全部语法的兼容(不推荐)

可惜的是,上面 preset 中的 @babel-preset-env 模块只能对一些普通的语法进行兼容性转换,而对于像 Promise 这类的高级语法就无能为力了,这时就可以用 @babel/polyfill 这个模块来完成这部分的工作了。

同样地,使用该模块前需要先安装:

$ npm i @babel/polyfill -D

使用该模块的方式不是像上面的 @babel-preset-env 一样,需要在 preset 属性中设置。而只需要在 js 文件中以模块的方式对其进行引入即可:

// .src/js/index.js

// 只需在 js 文件中以模块的方式将@babel/polyfill进行引入即可
import '@babel/polyfill';

const add = (x, y) => {
  return x + y;
};
console.log(add(2, 5));

const promise = new Promise(resolve => {
  setTimeout(() => {
    console.log('定时器执行完了~');
    resolve();
  }, 1000);
});

console.log(promise);

但是观察此时打包输出的 ./build/js/built.js 文件,可以发现该文件的体积比之前的大了好多,这是为什么呢?

原因就是 @babel/polyfill 进行语法兼容的方式就是非常粗暴地直接把所有的JavaScript兼容性问题一次性全部解决,并将所有的兼容性操作引入到了打包输出的 built.js 中。比如某个浏览器不支持 Promise ,那么 @babel/polyfill 解决该办法的方式就是直接在输出的 built.js 中手动实现了一个 Promise 来供浏览器调用。

JavaScript语法需要做的兼容性操作比较多,这就导致了包含了所有这些兼容性操作的 built.js 文件体积比较大。而且这种引入方式是全局的,所以可能会污染全局环境,所以这种方法一般不采用。

1.3、按需兼容(推荐)

上面的 @babel/polyfill 解决兼容性的方法太过粗暴,但是 @babel-preset-env 所能解决的兼容性问题的能力又不能我们对高级语法的需求。所以就有了这种按需兼容的解决方案。所谓按需兼容,就是在浏览器出现不兼容某个语法的时候对相应部分的代码做兼容性操作,这样既能满足我们的需求,又能避免不必要的开销。

这就需要 core-js 这个模块来实现了,老规矩,先下载:

$ npm i core-js -D

@babel-preset-env 使用时一样,我们需要在 webpack.config.jsmodulebabel-loader 中配置 preset 属性:

// webpack.config.js

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        // 同样地,做兼容性处理时应当排除第三方库中的js文件
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
        	// preset是预设的意思,该属性指示babel-loader对js文件做怎样的兼容性转化处理
          // 而在@babel-preset-env中就有一些对js基础语法的兼容性转化规则,其后的corejs
          // 则负责对用到的高级语法做兼容性转换,注意preset由之前的一维数组变为了二维数组
        	preset: [[
            '@babel-preset-env',
            // corejs的相关设置放在一个配置对象中
            {
              // useBuiltIns设置为usage可以理解为开启按需加载
              useBuiltIns: 'usage',
              // 指定使用的corejs版本
              corejs: {
                version: 3
              },
              // targets属性用于设置兼容性处理具体做到哪个浏览器版本
              targets: {
                chrome: '60',
                firefox: '60',
                ie: '9',
                safari: '10',
                edge: '17'
              }
            }
          ]]
        }
      }
    ]
  },
  plugins: [
    ...
  ],
  mode: 'development'
};

有了 core-js 来负责高级语法的兼容性处理,而之前的 @babel-preset-env 则负责普通语法的兼容性处理,这两者配合就能满足我们的兼容性处理需求了。

注意,使用了这两者做兼容性处理的话,就不要再引入 @babel/polyfill 了。

有关 babel-loader 的配置描述,也可以看下方的链接:

参考:babel-loader | webpack 中文网

参考:史上最清晰易懂的babel配置解析 - SegmentFault 思否

3、压缩JS

在webpack中设置压缩JS代码非常简单,只需要将 webpack.config.js 中的 mode 设置为 production 即可。因为在生产模式下,webpack会自动对代码进行压缩,在该模式下,webpack会自动调用一些压缩代码的插件。

三、对HTML的处理

.html 文件来说需要做的处理比较少,一般不需要考虑兼容性的问题。所以一般只进行压缩处理。而对 .html 文件的压缩是在此前提到的 html-webpack-plugin 这个插件的构造函数的配置对象中增加一个配置项:minify

// webpack.config.js

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

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {...}
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // 新增一个minify配置项来压缩html代码
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true
      }
    })
  ],
  // 将mode设置为生产模式可以自动压缩js代码
  mode: 'production'
};

四、生产环境下的webpack配置总结

该总结于 2021年10月17日15:19:14 更新,增加了详细的注释解释。

/*
 * @Descripttion: Webpack 生产环境下的配置
 * @version: 1.0
 * @Author: LiarCoder
 * @Date: 2021-10-17 13:05:56
 * @LastEditors: LiarCoder
 * @LastEditTime: 2021-10-17 15:14:30
 */

// webpack.config.production.js

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

// 手动设置 Node.js 环境变量为 development,注意这里的设置和下面的 mode 设置无关
process.env.NODE_ENV = 'development';

// 因为下面的loader配置在处理css文件和less文件时都要用到,为了复用代码,可以将公共部分提取出来
const commonCssLoader = [
  // 注意各个loader的执行顺序是由上到下,由后到前的
  // MiniCssExtractPlugin.loader用于将js中的样式字符串提取到一个单独的css文件中
  MiniCssExtractPlugin.loader,
  // css-loader用于将源css文件变成CommonJS模块加载到js中,里面内容是样式字符串
  'css-loader',
  // postcss-loader用于对源css文件做兼容性处理,它需要借助postcss-preset-env插件来读取
  // package.json中的browserslist配置项,该配置项可以指定根据具体的浏览器版本来做兼容处理
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
      // 还要在项目根目录下的 package.json 中增加 browserslist 配置项
      // "browserslist": {
      //   // 项目运行时如果设置为开发环境,则加载development中的配置
      //   // 开发时的要求不是那么严格,只要兼容一些主流浏览器的最新版本已完成调试工作就可以了
      //   "development": [
      //     // 兼容Chrome最近的一个版本
      //     "last 1 chrome version",
      //     // 兼容Firefox最近的一个版本
      //     "last 1 firefox version",
      //     // 兼容Safari最近的一个版本
      //     "last 1 safari version"
      //   ],
      //   // 项目运行时如果设置为生产环境,则加载production中的配置(默认情况读取该配置)
      //   // 生产环境的要求就高一点了,需要考虑实际运行时可能会出现的兼容问题
      //   "production": [
      //     // 兼容0.2%以上的浏览器
      //     ">0.2%",
      //     // 不兼容已经消亡的浏览器
      //     "not dead",
      //     // 不兼容所有op_mini浏览器
      //     "not op_mini all"
      //   ]
      // }
    }
  }]

module.exports = {
  entry: '.src/js/index.js',
  output: {
    path: resolve(__dirname, 'build'),
    filename: 'js/built.js'
  },
  // 配置各个loader
  module: {
    rules: [{
      // 使用 url-loader 处理样式代码中所用到的图片资源
      test: /\.(png|jpg|gif)$/,
      // 如果只使用一个loader,那么就直接用loader属性指明
      loader: 'url-loader',
      // options用于设置打包时的额外配置
      options: {
        // 如果当前图片的大小小于8KB,那么打包时就会将该图片转化为base64格式
        limit: 8 * 1024,
        // 可以通过name来设置打包输出的图片的名称格式,
        // 下面的意思是取图片hash值的前十位,并保持原来的扩展名
        name: '[hash:10].[ext]',
        // 因为url-loader工作时采用的默认模块化机制是ES6模块,而下面的html-loader
        // 默认采用的是CommonJS模块机制,为了避免错误,需要手动关闭url-loader的模块化设置
        // 从而使其采用CommonJS模块规范
        esModule: false,
        // 为了使输出的图片资源所在目录与src下的保持一致,可以设置outputPath属性为相应值
        outputPath: 'img'
      }
    }, {
      // 匹配html文件,html-loader是专门用于处理html文件中的<img>标签中的图片资源的,
      // html-loader 是负责将 <img> 标签中的图片资源引入进来,从而让 url-loader 能够处理,
      // 它需要和上面的 url-loader 配合使用
      test: /\.html$/,
      loader: 'html-loader'
    }, {
      // 因为在处理css文件和less文件时会重复使用某些代码,为了复用代码,可以将公共部分提取出来
      test: /\.css$/,
      use: [...commonCssLoader]
    }, {
      // 处理less文件时需要先将 less 代码通过 less-loader 转化为 css 代码,之后就是普通的处理css的流程
      test: /\.less$/,
      use: [...commonCssLoader, 'less-loader']
    }, {
      // 用 eslint-loader 来对源 js 文件做语法检查,注意该loader及其检查规则airbnb
      // 依赖于其他的基础模块,所以在使用前应该先对这些模块进行本地下载:
      // eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import
      test: /\.js$/,
      // 注意,检查时应当排除第三方库中的js文件(即node_modules目录下的文件),
      // 因为这些文件都发布前都已经检查过了,我们没必要重复检查,那样很费时间,
      // 所以只需要检查自己写的 js 源代码文件
      exclude: /node_modules/,
      // 一个文件一般只被一个loader处理,如果有多个loader配置都是针对同一种类型的文件
      // 那么就需要手动设置哪个loader先执行,通过设置eslint-loader中的enforce为pre
      // 就可以让该loader先于其他loader执行。
      enforce: 'pre',
      loader: 'eslint-loader',
      options: {
        // 开启eslint检查可能会在打包时出现许多报错或者警告,我们可以根据这些提示信息
        // 手动对相应位置的代码进行修改,设置fix为true则会在检查时自动对报错的代码进行修改
        // 自动修复eslint的错误
        fix: true
      }
      // 还要在项目根目录下的 package.json 中增加 eslintConfig 配置项
      // "eslintConfig": {
      //   // 使用extends属性来让eslint继承airbnb-base的js语法检查规则
      //   "extends": "airbnb-base"
      // }
      // 如果想要 eslint 在检查时忽略某一行代码,则需要在该行代码前加上注释:// eslint-disable-next-line
    }, {
      // 使用 babel-loader 来对 js 做兼容性处理,注意该loader依赖于其他的基础模块,
      // 所以在使用前应该先对这些模块进行本地下载:
      // @babel/core babel-loader @babel-preset-env core-js
      test: /\.js$/,
      loader: 'babel-loader',
      options: {
        // preset 是预设的意思,该属性指示 babel-loader 对 js 文件做怎样的兼容性转化处理
        // 而在 @babel-preset-env 中就有一些对 js 基础语法的兼容性转化规则,其后的 corejs
        // 则负责对用到的高级语法做兼容性转换,注意 preset 由之前的一维数组变为了二维数组
        preset: [['@babel/preset-env',
          // corejs的相关设置放在一个配置对象中
          {
            // useBuiltIns设置为usage可以理解为开启按需加载
            useBuiltIns: 'usage',
            // 指定使用的corejs版本
            corejs: {
              version: 3
            },
            // targets属性用于设置兼容性处理具体做到哪个浏览器版本
            targets: {
              chrome: '60',
              firefox: '60',
              ie: '9',
              safari: '10',
              edge: '17'
            }
          }]]
      }
    }, {
      // 除了上述提到的这些类型的资源,其他资源都使用 file-loader 来进行打包处理
      exclude: /\.(js|html|css|less|png|jpg|gif)$/,
      // file-loader 会将资源以原本的形式输出,而上面提到的 url-loader 依赖于此,
      // url-loader 是在 file-loader 的基础上做了一些优化,比如上面 limit 设置
      loader: 'file-loader',
      options: {
        // 同样为了保持输出目录与原来的目录保持一致,可以设置 outputPath 为相应的值
        outputPath: 'media'
      }
    }]
  },
  // 配置各个插件,注意 plugins 的值是一个数组,使用插件之前一定要在将其引入,引入的结果往往
  // 是一个构造函数,而使用插件就是调用该构造函数,按需求还可以传入一个配置对象作为参数
  plugins: [
    // 使用之前引入的构造函数并传入一个配置对象
    new HtmlWebpackPlugin({
      // template用于指示输出的html文件以谁为模板,webpack打包时会将项目中用到js资源插入其中
      template: './src/index.html',
      // 新增一个 minify 配置项来压缩 html 代码
      minify: {
        // 移除 html 文件中的空格
        collapseWhitespace: true,
        // 移除 html 文件中的注释
        removeComments: true
      }
    }),
    // 如果不给构造函数传入配置对象参数,则会默认在 build 目录下输出一个 main.css 样式文件
    // new MiniCssExtractPlugin()
    new MiniCssExtractPlugin({
      // 可以通过配置对象中 filename 属性来对输出的 css 文件进行重命名和目录指定
      filename: 'css/built.css'
    }),
    // 调用一下上面引入的插件的构造函数来压缩 css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  // 将 mode 设置为生产模式可以自动压缩 js 代码
  mode: 'production'
}

结束:2021年10月17日02:04:31

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值