webpack 基础

148 阅读12分钟

webpack 基础

webpack 简介

webpack 是什么

本质上,webpack 是一种前端资源构建工具,一个现代 JavaScript 应用程序的静态模块打包器(module bundler)

在 webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理;它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。

  • 入口文件 -> chunk(jQuery、less、sass...)-> 打包(less-css, js-js, ...)-> bundle出口文件

webpack 五个核心概念

1.Entry

  • 入口(Entry)指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图

2.Output

  • 输出(Output)指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名

3.Loader

  • Loader 让 webpack 能 够 去 处 理 那 些 非 JavaScript 文 件 (webpack 自 身 只 理 解 JavaScript)。

4.Plugins

  • 插件(Plugins)可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩, 一直到重新定义环境中的变量等。

5.Mode

  • 模式(Mode)指示 webpack 使用相应模式的配置。 | 选项 | 描述 | 特点 | | --- | --- | --- | | development | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置 为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin | 能让代码本地调试 运行的环境 | | production | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置 为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。 | 能让代码优化上线 运行的环境 |

webpack 初体验

初始化配置

初始化 package.json

npm init

下载并安装 webpack

// 全局安装
npm install webpack webpack-cli -g
// 本地安装
npm install webpack webpack-cli -D

编译打包应用

创建文件

- index.js // 入口文件
- build // 打包结果文件夹

运行指令

  • 开发环境指令:

    • webpack src/js/index.js -o build/js/built.js --mode=development
    • 功能:webpack 能够编译打包 js 和 json 文件,并且能将 es6 的模块化语法转换成 浏览器能识别的语法。
  • 生产环境指令:

    • webpack src/js/index.js -o build/js/built.js --mode=production
    • 功能:在开发配置功能上多一个功能,压缩代码。

结论

  • webpack 能够编译打包 js 和 json 文件
  • 能将 es6 的模块化语法转换成浏览器能识别的语法
  • 能压缩代码

问题

  • 不能编译打包 css、img 等文件
  • 不能将 js 的 es6 基本语法转化为 es5 以下语法

webpack 开发环境基本配置

创建配置文件

  • 创建文件 webpack.config.js
  • 配置内容如下
/**
 * webpack.config.js:webpack的配置文件
 * 作用:指示 webpack可以做哪些工作(当运行 webpack指令时,会加载里面的配置)
 * 
 * 所有构建工具都是基于 nodejs平台运行的~模块化采用 commonjs
 * 
 */
// nodejs方法
// resolve用来拼接绝对路径的方法
const { resolve } = require('path')
module.exports = {
  // webpack配置
  // 入口路径
  entry: './src/index.js',
  // 输出
  output: {
    // 输出文件名:
    filename: 'built.js',
    // 输出路径:
    // __dirname: nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'build')
  },
  // loader的配置
  module: {
    rules: [
      // 详细loader的配置
    ]
  },
  // plugins的配置
  plugins: [
    // 详细plugins的配置
  ],
  // 模式:只能选一个
  mode: 'development',
  // mode: 'production'
}

  • 运行指令: webpack
  • 结论: 此时功能与上面的指令一致

打包样式资源

  • 创建文件 index.css、index.less
  • 下载安装 loader 包
npm i css-loader style-loader less-loader less -D
  • 修改配置文件,如下
/**
 * webpack.config.js:webpack的配置文件
 * 作用:指示 webpack可以做哪些工作(当运行 webpack指令时,会加载里面的配置)
 * 
 * 所有构建工具都是基于 nodejs平台运行的~模块化采用 commonjs
 * 
 */
// nodejs方法
// resolve用来拼接绝对路径的方法
const { resolve } = require('path')
module.exports = {
  // webpack配置
  // 入口路径
  entry: './src/index.js',
  // 输出
  output: {
    // 输出文件名:
    filename: 'built.js',
    // 输出路径:
    // __dirname: nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'build')
  },
  // loader的配置
  module: {
    rules: [
      // 详细loader的配置
      {
        // 匹配的文件
        test: /\.css$/,
        // 使用那些 loader进行处理
        use: [ // use中的 loader执行顺序:从右到左,依次执行
          // 创建 style标签,将 js中的样式资源插入到 head中生效
          'style-loader',
          // 将 .css文件变成 CommonJS模块加载到 js中,里面内容是样式字符串
          'css-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          // 将 less文件编译成 css文件
          'less-loader'
        ]
      }
    ]
  },
  // plugins的配置
  plugins: [
    // 详细plugins的配置
  ],
  // 模式:只能选一个
  mode: 'development',
  // mode: 'production'
}

  • 运行指令: webpack
  • 运行结果
<!-- 手动创建此文件 -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title></title>
</head>

<body>
  <h2 id="title">webpack</h2>
  <!-- 手动引入 .js文件 -->
  <script src='./built.js'></script>
</body>

</html>

打包 HTML 资源

  • 创建文件
  • 下载安装 plugin 包
npm install --save-dev html-webpack-plugin
  • 修改配置文件
/**
 * loader:
 * 1.下载
 * 2.使用(配置loader)
 * plugin:
 * 1.下载
 * 2.引入
 * 3.使用
 */
const { resolve }  = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
    ]
  },
  plugins: [
    // plugins的配置
    // html-webpack-plugin处理 html文件
    // 功能:默认创建一个空的 HTML文件,自动引入打包输出的所有文件(js、css)
    // 需求:需要有结构的 HTML文件,解决方法如下
    new HtmlWebpackPlugin({
      // 复制此文件 './src/index.html',并自动引入打包输出的所有文件(js、css)
      template: './src/index.html'
    })
  ],
  mode: 'development'
}
  • 运行指令: webpack
  • 运行结果
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
<script defer src="built.js"></script></head>

<body>
  <h2 id="title">webpack</h2>
</body>

</html>

打包图片资源 -7

  • 创建文件
  • 下载安装 loader 包
npm install --save-dev html-loader url-loader file-loader
  • 修改配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.less$/,
        // 要使用多个loader处理用use
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        // 问题:默认处理不了html中img图片
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        // 使用一个loader
        // 下载 url-loader file-loader
        loader: 'url-loader',
        options: {
          // 图片大小小于8kb,就会被base64处理
          // 优点: 减少请求数量(减轻服务器压力)
          // 缺点:图片体积会更大(文件请求速度更慢)
          limit: 8 * 1024,
          // 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
          // 解析时会出问题:[object Module]
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule: false,
          // 给图片进行重命名
          // [hash:10]取图片的hash的前10位
          // [ext]取文件原来扩展名
          name: '[hash:10].[ext]'
        }
      },
      {
        test: /\.html$/,
        // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
        loader: 'html-loader'
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development'
};

  • 运行指令: webpack
  • 结果如下:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
<script defer src="built.js"></script></head>

<body>
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="box3"></div>
  <img src="b222d3274a.png" alt="webpack">
</body>

</html>

打包其它资源(字体图标...) -8

  • 创建文件
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      // 打包其它资源,除了(css|js|html)以外的资源
      {
        exclude: /\.(css|js|html)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development'
}
  • 运行指令: webpack

devServer -9

  • 特点:只会在内存中编译打包,不会有任何输出
  • 创建文件
  • 下载 devServer
npm - webpack-dev-server -D
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      // 打包其它资源,除了(css|js|html)以外的资源
      {
        exclude: /\.(css|js|html)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  /**
   * 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)
   * 特点:只会在内存中编译打包,不会有任何输出
   * 启动指令为:npx webpack-dev-server
   */
  devServer: {
    // 被运行的目录
    contentBase: resolve(__dirname, 'build'),
    // 启用 gzip压缩
    compress: true,
    // 端口号
    port: 3030,
    // 自动打开浏览器
    open: true
  }
}
  • 运行指令: npx webpack-dev-server

开发环境整体配置

  • 创建文件
    - src
    -- js
    -- css
    -- imgs
    -- media
    - index.html
    - webpack.config.js
    
  • 修改配置文件
// package.json
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^5.2.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^5.3.1",
    "less": "^4.1.1",
    "less-loader": "^8.1.0",
    "style-loader": "^2.0.0",
    "url-loader": "^3.0.0",
    "webpack": "^5.32.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.11.2"
  }
}

// webpack.config.js
/**
 * 开发环境的配置:代码运行即可
 */
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    // 输出到js/ 文件夹下
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // css资源不用单独打包到文件夹,它们都被打包到 .js中了
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader'
        ]
      },
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
        test: /\.(png|gif|jpg|jpeg)$/,
        // 处理样式中的图片资源
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          esModule: false,
          name: '[hash:10].[ext]',
          // outputPath:指定输出结果所在的文件夹
          outputPath: 'imgs'
        }
      },
      {
        test: /\.html$/,
        // 处理 HTML中的 img资源
        loader: 'html-loader'
      },
      {
        exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
        // 将资源原封不动的输出出去
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3030,
    open: true
  }
}
  • 运行指令:
    • npx webpack-dev-server 只在内存中生成打包的结果文件
    • webpack 在硬盘中生成打包后的结果文件

webpack 生产环境基本配置

主要任务:

  1. 将 css从 js中分离
  2. 代码压缩
  3. 兼容性处理
  4. 其它

目的:

  1. 项目更快
  2. 更平稳

提取 css成单独文件

  • 下载安装包
  • 下载插件
    npm i mini-css-extract-plugin@0.9.0 -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标签,将其放到 head标签中
          // 'style-loader',
          // 使用此 loader取代 style-loader;
          // 作用:提取js中的 css成单独文件
          /**
           * 优点:
           * 1.将 css文件以 link标签的形式引入而不是 style标签的形式,
           * 避免闪屏现象
           * 2.将 css与 js文件分隔开,减小体积,加载速度更快
           */
          MiniCssExtractPlugin.loader,
          // 将 css文件整合到 js文件中
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的 css文件进行重命名
      filename: 'css/built.css'
    })
  ],
  // mode: 'production'
  mode: 'development'
}

// package.json
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel": "^6.23.0",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "terser-webpack-plugin": "^2.3.5",
    "thread-loader": "^2.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.0.0"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}
  • 运行指令: webpack

css 兼容性处理 -13

  • 创建文件
  • 下载 loader
    npm install --save-dev postcss-loader postcss-preset-env
    
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

/**
 * 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的环境变量,默认是 'production'
// process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          // 将 css文件整合到 js文件中
          'css-loader',
          /**
           * css兼容性处理:
           * postcss ->
           * postcss-loader ->
           * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
           */
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                /**
                 * postcss的插件
                 * 帮助 postcss找到 package.json中 browserslist里面的配置,
                 * 通过配置加载指定的 css兼容性样式
                 */
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的 css文件进行重命名
      filename: 'css/built.css'
    })
  ],
  // mode: 'production'
  mode: 'development'
}
  • 修改 package.json
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel": "^6.23.0",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "terser-webpack-plugin": "^2.3.5",
    "thread-loader": "^2.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.0.0"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}

  • 运行指令: webpack

css 压缩

  • 创建文件
  • 下载安装包
    npm install --save-dev optimize-css-assets-webpack-plugin
    
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 将css提取到单独的文件容
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// css压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

/**
 * browserslist
 * // 开发环境:设置 node环境变量:process.env.NODE_ENV = 'development'
 * "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    // 生产环境:默认是看生产环境
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
 */

// 设置 nodejs的环境变量,默认是 'production'
// process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          // 将 css文件整合到 js文件中
          'css-loader',
          /**
           * css兼容性处理:
           * postcss ->
           * postcss-loader ->
           * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
           */
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                /**
                 * postcss的插件
                 * 帮助 postcss找到 package.json中 browserslist里面的配置,
                 * 通过配置加载指定的 css兼容性样式
                 */
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的 css文件进行重命名
      filename: 'css/built.css'
    }),
    // 压缩 css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  // mode: 'production'
  mode: 'development'
}

// package.json
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel": "^6.23.0",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "terser-webpack-plugin": "^2.3.5",
    "thread-loader": "^2.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.0.0"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}

  • 运行指令: webpack

js 语法检查

  • 创建文件
  • 下载安装包
    npm install --save-dev eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
    
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 将css提取到单独的文件容
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// css压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

/**
 * browserslist
 * // 开发环境:设置 node环境变量:process.env.NODE_ENV = 'development'
 * "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    // 生产环境:默认是看生产环境
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
 */

// 设置 nodejs的环境变量,默认是 'production'
// process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // 语法检查:规范项目代码,检查常见语法错误
      {
        /**
         * 只检查源代码,忽略第三方库
         * eslint-loader
         * eslint
         * 设置检查规则:
         *    在 package.json的 eslintConfig中设置;
         *    推荐使用 airbnb -> 依赖 eslint-config-airbnb-base、eslint-plugin-import
         */
        test: /\.js$/,
        // 排除 node_modules中的 .js
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // 自动修复 eslint错误
          fix: true
        }
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          // 将 css文件整合到 js文件中
          'css-loader',
          /**
           * css兼容性处理:
           * postcss ->
           * postcss-loader ->
           * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
           */
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                /**
                 * postcss的插件
                 * 帮助 postcss找到 package.json中 browserslist里面的配置,
                 * 通过配置加载指定的 css兼容性样式
                 */
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的 css文件进行重命名
      filename: 'css/built.css'
    }),
    // 压缩 css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  // mode: 'production'
  mode: 'development'
}
  • 配置 package.json
{
  "name": "webpack_code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.4",
    "@babel/polyfill": "^7.8.3",
    "@babel/preset-env": "^7.8.4",
    "add-asset-html-webpack-plugin": "^3.1.3",
    "babel": "^6.23.0",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "file-loader": "^5.0.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "terser-webpack-plugin": "^2.3.5",
    "thread-loader": "^2.1.3",
    "url-loader": "^3.0.0",
    "webpack": "^4.41.6",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.0.0"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}

  • 运行指令: webpack

js兼容性处理

  • 创建文件
  • 下载安装包
    npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/polyfill core-js
    
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 将css提取到单独的文件容
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// css压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

/**
 * browserslist
 * // 开发环境:设置 node环境变量:process.env.NODE_ENV = 'development'
 * "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    // 生产环境:默认是看生产环境
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
 */

// 设置 nodejs的环境变量,默认是 'production'
// process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // js兼容性处理:babel-loader、@babel/preset-env、@babel/core
      {
        /**
         * loader
         * 1.简单的 js兼容操作:@babel/preset-env
         *  问题:只能转换基本语法,如 promise不能转换
         *
         * 2.全部 js兼容性处理(不推荐):@babel/polyfill,只需要在 .js文件中引入即可
         *  问题:当只解决部分兼容性1问题时,但将所有兼容性代码都引入了,体积太大
         * 
         * 3.按需加载要兼容的代码(推荐):core-js
         * 
         * 总结:通过 1.和3.分别完成基本的兼容性处理和高级语法的兼容性处理
         */
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设:指示 babel做怎样的兼容处理
          presets: [
            [
              '@babel/preset-env',
              {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定 core-js版本
                corejs: {
                  version: 3
                },
                // 指定兼容性做到那个版本的浏览器
                targets: {
                  chrome: '60',
                  firefox: '50',
                  ie: '9',
                  safari: '10',
                  edge: '17'
                }
              }
            ]
          ]
        }
      },
      // 语法检查:规范项目代码,检查常见语法错误
      {
        /**
         * 只检查源代码,忽略第三方库
         * eslint-loader
         * eslint
         * 设置检查规则:
         *    在 package.json的 eslintConfig中设置;
         *    推荐使用 airbnb -> 依赖 eslint-config-airbnb-base、eslint-plugin-import
         */
        test: /\.js$/,
        // 排除 node_modules中的 .js
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // 自动修复 eslint错误
          fix: true
        }
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          // 将 css文件整合到 js文件中
          'css-loader',
          /**
           * css兼容性处理:
           * postcss ->
           * postcss-loader ->
           * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
           */
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                /**
                 * postcss的插件
                 * 帮助 postcss找到 package.json中 browserslist里面的配置,
                 * 通过配置加载指定的 css兼容性样式
                 */
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的 css文件进行重命名
      filename: 'css/built.css'
    }),
    // 压缩 css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  // mode: 'production'
  mode: 'development'
}
  • 运行指令: webpack

js 压缩

  • 创建文件
  • 修改配置文件
    // 生产环境下会自动压缩 js 代码
    // 使用的是 webpack的内置压缩插件 UglifyJsPlugin
    mode: 'production'
    
  • 运行指令: webpack

html 压缩

  • 创建文件
  • 修改配置文件
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 将css提取到单独的文件容
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// css压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

/**
 * browserslist
 * // 开发环境:设置 node环境变量:process.env.NODE_ENV = 'development'
 * "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    // 生产环境:默认是看生产环境
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
 */

// 设置 nodejs的环境变量,默认是 'production'
// process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // js兼容性处理:babel-loader、@babel/preset-env、@babel/core
      {
        /**
         * loader
         * 1.简单的 js兼容操作:@babel/preset-env
         *  问题:只能转换基本语法,如 promise不能转换
         * 
         * 2.全部 js兼容性处理(不推荐):@babel/polyfill,只需要在 .js文件中引入即可
         *  问题:当只解决部分兼容性问题时,但将所有兼容性代码都引入了,体积太大
         * 
         * 3.按需加载要兼容的代码(推荐):core-js
         * 
         * 总结:通过 1.和3.分别完成基本的兼容性处理和高级语法的兼容性处理
         */
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设:指示 babel做怎样的兼容处理
          presets: [
            [
              '@babel/preset-env',
              {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定 core-js版本
                corejs: {
                  version: 3
                },
                // 指定兼容性做到那个版本的浏览器
                targets: {
                  chrome: '60',
                  firefox: '50',
                  ie: '9',
                  safari: '10',
                  edge: '17'
                }
              }
            ]
          ]
        }
      },
      // 语法检查:规范项目代码,检查常见语法错误
      {
        /**
         * 只检查源代码,忽略第三方库
         * eslint-loader
         * eslint
         * 设置检查规则:
         *    在 package.json的 eslintConfig中设置;
         *    推荐使用 airbnb -> 依赖 eslint-config-airbnb-base、eslint-plugin-import
         */
        test: /\.js$/,
        // 排除 node_modules中的 .js
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // 自动修复 eslint错误
          fix: true
        }
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          // 将 css文件整合到 js文件中
          'css-loader',
          /**
           * css兼容性处理:
           * postcss ->
           * postcss-loader ->
           * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
           */
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                /**
                 * postcss的插件
                 * 帮助 postcss找到 package.json中 browserslist里面的配置,
                 * 通过配置加载指定的 css兼容性样式
                 */
                require('postcss-preset-env')()
              ]
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html代码压缩
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true
      }
    }),
    new MiniCssExtractPlugin({
      // 对输出的 css文件进行重命名
      filename: 'css/built.css'
    }),
    // 压缩 css
    new OptimizeCssAssetsWebpackPlugin()
  ],
  // production环境下自动压缩 .js文件代码
  mode: 'production'
  // mode: 'development'
}
  • 运行指令:webpack

生产环境配置

  • 修改配置文件
// nodejs
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 将 css从 js中提取出来,并到单独的文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// css代码压缩
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

// 定义 nodejs环境变量:决定使用 browserslist的哪个环境
process.env.NODE_ENV = 'production'
// process.env.NODE_ENV = 'development'

// loader复用
const commonCSSLoader = [
  // 将 css代码提取到一个指定的文件中
  MiniCssExtractPlugin.loader,
  // 将 css加载到 js中
  'css-loader',
  /**
   * css兼容性处理:只能针对 css代码来操作
   * postcss ->
   * postcss-loader ->
   * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
   */
  {
    /**
     * 需要在 package.json中定义 browserslist里面的配置
     */
    loader: 'postcss-loader',
    options: {
      // 告诉它要做哪些兼容性配置
      ident: 'postcss',
      plugins: () => [
        /**
         * postcss的插件
         * 帮助 postcss找到 package.json中 browserslist里面的配置,
         * 通过配置加载指定的 css兼容性样式
         */
        require('postcss-preset-env')()
      ]
    }
  }
]

// commonjs
module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // css代码处理
      {
        test: /\.css$/,
        use: [
          ...commonCSSLoader
          // // 将 css代码提取到一个指定的文件中
          // MiniCssExtractPlugin.loader,
          // // 将 css加载到 js中
          // 'css-loader',
          // /**
          //  * css兼容性处理:只能针对 css代码来操作
          //  * postcss ->
          //  * postcss-loader ->
          //  * postcss-preset-env:帮助 postcss识别某些环境,加载指定的配置
          //  */
          // {
          //   /**
          //    * 需要在 package.json中定义 browserslist里面的配置
          //    */
          //   loader: 'postcss-loader',
          //   options: {
          //     // 告诉它要做哪些兼容性配置
          //     ident: 'postcss',
          //     plugins: () => [
          //       /**
          //        * postcss的插件
          //        * 帮助 postcss找到 package.json中 browserslist里面的配置,
          //        * 通过配置加载指定的 css兼容性样式
          //        */
          //       require('postcss-preset-env')()
          //     ]
          //   }
          // }
        ]
      },
      {
        test: /\.less$/,
        use: [
          ...commonCSSLoader,
          // MiniCssExtractPlugin.loader,
          // 'css-loader',
          'less-loader'
        ]
      },
      /**
       * 正常来讲,一个文件只能被一个 loader处理;
       * 当一个文件要被多个 loader处理,那一定要指定 loader执行的先后顺序
       * 如下面的 .js文件:应该先执行 eslint再执行 bable,通过 enforce属性指定
       */
      // js语法检查:规范项目代码,检查常见语法错误
      {
        /**
         * 只检查源代码,忽略第三发库
         * eslint-loader
         * eslint
         * 在 package.json的 eslintConfig中设置检查规则,推荐 airbnb
         */
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行此 loader
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          // 自动修复 eslint错误
          fix: true
        }
      },
      {
        // js兼容性处理:babel-loader、@babel/preset-env、@babel/core
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设:指示 babel做怎样的兼容处理
          presets: [
            [
              // 只能作简单的语法兼容处理
              '@babel/preset-env',
              // corejs可以作复杂的语法兼容处理
              {
                // 按需加载
                useBuiltIns: 'usage',
                // 指定 core-js版本
                corejs: {
                  version: 3
                },
                // 指定兼容性做到哪个版本的浏览器
                targets: {
                  chrome: '60',
                  firefox: '50',
                  safari: '10',
                  edge: '17',
                  ie: '9'
                }
              }
            ]
          ]
        }
      },
      // 处理图片资源
      {
        test: /\.(png|gif|jpg|jpeg)$/,
        loader: 'url-loader',
        options: {
          // 对于图片小于 8-12kb的可以进行 base64处理
          limit: 8 * 1024,
          // 关闭 ES6解析,使用 commonjs解析
          esModule: false,
          name: '[hash:10].[ext]',
          outputPath: 'imgs'
        }
      },
      // 处理 HTML中的 img资源
      {
        test: /\.html$/,
        // 处理 HTML中的 img资源
        loader: 'html-loader'
      },
      // 处理其它资源
      {
        exclude: /\.(html|js|css|less|png|gif|jpg|jpeg)/,
        // 将其它资源原封不动的输出
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // html代码压缩
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    }),
    new MiniCssExtractPlugin({
      // 对提取出的 css代码放到统一的文件中,并命名
      filename: 'css/built.css'
    }),
    // css代码压缩
    new OptimizeCssAssetsWebpackPlugin()
  ],
  mode: 'production'
}

webpack 优化配置

webpack 优化配置

HMR

source-map

oneOf

缓存

tree shaking

code split

lazy loading

pwa

多进程打包

externals

dll

webpack 原理分析

webpack5 介绍