webpack 配置汇总


1. webpack 介绍

返回目录
webpack 是用于打包 JavaScript 项目的。可以在 cli (命令行) 和 API 中调用其接口。

2. 安装 Webpack

返回目录

  1. 要安装的包
    包名说明环境
    webpackwebpack 主程序dev
    webpack-cliwebpack 命令行工具dev
  2. 安装命令
    mkdir webpackdemo #新建项目目录
    cd webpackdemo #进入目录
    npm init -y #初始化 node,生成 package.json
    npm install --save-dev webpack webpack-cli #安装 webpack
    
  3. webpack 的默认配置
    默认入口是 / src / index.js
    默认出口是 / dist / main.js

3. 使用 webpack 打包 js 项目

返回目录

  1. 创建 index.js 和 webpack 配置文件
      webpack-demo
    + |- /src #源码目录
    +   |- index.js #示例代码文件
      |- package.json
    + |- webpack.config.js #webpack配置文件
    
  2. index.js
    function main() {
      console.log("hello, webpack!");
    }
    main();
    
  3. webpack.config.js
    const path = require("path");
    
    module.exports = {
      entry: "./src/index.js", //入口文件
      output: {
        filename: "js/[name].[hash:8].bundle.js", //出口文件
        path: path.resolve(__dirname, "dist") //输出路径
      }
    };
    
  4. package.json
      {
        "name": "webpack-demo",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
    +     "start": "webpack --progress"
        },
        "keywords": [],
        "author": "",
        "license": "ISC",
        "devDependencies": {
          "webpack": "^4.42.0",
          "webpack-cli": "^3.3.11"
        }
      }
    
    注意:test 命令后面的逗号别忘了。
  5. 执行命令 npm start进行打包
    如果 webpack.config.js 存在,则 webpack 默认情况下该命令将其选中。参数 --config 的使用只是为了表明可以传递任何名称的配置。这对于需要拆分为多个文件的更复杂的配置很有用。

4. 清除打包的旧文件

返回目录

  1. 需要安装插件
    包名说明环境
    clean-webpack-plugin清空构建文件夹dev
  2. 安装命令
    npm install --save-dev clean-webpack-plugin
    
  3. webpack.config.js
      const path = require('path');
    + //引入插件
    + const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
      module.exports = {
        entry: './src/index.js', //入口文件
    +   //配置插件
    +   plugins: [
    +     new CleanWebpackPlugin(),
    +   ],
        output: {
          filename: 'js/[name].[hash:8].bundle.js',
          path: path.resolve(__dirname, 'dist'),
        },
      };
    
  4. 执行命令 npm start进行打包

5. 使用 Babel 对 js 转译

返回目录
babel 很复杂的,只是写了常用配置,更详细的去官网查看

  1. 需要安装的包

    包名说明环境
    babel-loaderBabel 加载器dev
    @babel/coreBabel 核心包dev
    @babel/cliBable 命令行dev
    @babel/preset-env根据配置的目标浏览器或运行环境,自动的将代码转为 es5dev
    @babel/plugin-transform-runtimegenerator、Array.from 等新功能的支持dev
    @babel/runtime-corejs3@babel/plugin-transform-runtime 的依赖运行时prod
  2. 安装命令

    npm i -D babel-loader @babel/core @babel/cli @babel/preset-env @babel/plugin-transform-runtime
    npm i -S @babel/runtime-corejs3
    
  3. 新建 .babelrc.js 配置文件

      webpack-demo
      |- /src
        |- index.js
    + |- .babelrc.js
      |- package.json
      |- webpack.config.js #配置文件
    
  4. .babelrc.js

    const presets = [
      "@babel/preset-env",
    ];
    
    const plugins = [
      [
        "@babel/plugin-transform-runtime", //避免全局污染,支持新功能
        {
          corejs: 3,
          version: "7.8.7" //版本支持越高,支持的新功能越多
        }
      ]
    ];
    
    module.exports = { presets, plugins };
    
  5. webpack.config.js

      const path = require('path');
      //引入插件
      const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
      module.exports = {
      entry: './src/index.js', //入口文件
    +   //配置加载器
    +   module: {
    +     rules: [
    +       {
    +         test: /\.js|jsx$/, //匹配 js 文件
    +         exclude: /node_modules/, //排除文件夹
    +         use: [
    +           { loader: 'babel-loader' }, //使用babel
    +         ]
    +       },
    +     ]
    +   },
        //配置插件
        plugins: [
          new CleanWebpackPlugin(),
        ],
        output: {
          filename: 'js/[name].[hash:8].bundle.js',
          path: path.resolve(__dirname, 'dist'),
        },
      };
    
  6. 执行 npx webpacknpm start打包项目。

6. 在 webpack 配置文件中判断构建环境

返回目录

  1. 要安装的包
    包名说明环境
    cross-env配置环境变量dev
    1. 安装命令
    npm install --save-dev cross-env
    
  2. package.json
      {
        "name": "webpack-demo",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
    -     "start": "webpack --progress"
    +     "start": "cross-env NODE_ENV=development webpack --progress",
    +     "build": "cross-env NODE_ENV=production webpack --progress"
        },
        "keywords": [],
        "author": "",
        "license": "ISC",
        "devDependencies": {
          //...省略
        }
      }
    
  3. webpack.config.js
      const path = require('path');
        //引入插件
      const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    
    + const isProd = process.env.NODE_ENV === 'production'
    
      module.exports = {
    +   mode: process.env.NODE_ENV, //编译环境 开发development 生产production
        entry: './src/index.js', //入口文件
        //...省略
        output: {
    -     filename: "js/[name].bundle.js", //出口文件
    +     filename: `js/[name]${isProd?'.[hash:8]':''}.bundle.js`, //出口文件
          path: path.resolve(__dirname, 'dist'), //输出路径
        },
      }
    

7. 使用 webpack 打包 web 项目

返回目录

  1. 新建 index.html 模版文件
      webpack-demo
    + |- /public
    +   |- index.html # html 模版
      |- /src
        |- index.js
      |- .babelrc.js
      |- package.json
      |- webpack.config.js #配置文件
    
  2. index.html
    <!doctype html>
    <html>
      <head>
        <!-- 页面标题 html-webpack-plugin 插件替换 -->
        <title><%= htmlWebpackPlugin.options.title %></title>
      </head>
      <body>
      </body>
    </html>
    
  3. index.js
    - function main() {
    -   console.log('hello, webpack!');
    - }
    - main();
    + function component() {
    +   const element = document.createElement('div');
    +   element.innerHTML ='Hello webpack';
    +   return element;
    + }
    + document.body.appendChild(component());
    
  4. 需要安装的包
    包名说明环境
    html-webpack-plugin自动修改的 htmldev
  5. 安装命令
    npm install --save-dev html-webpack-plugin
    
  6. webpack.config.js
      const path = require('path');
      //引入插件
      const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    + const HtmlWebpackPlugin = require('html-webpack-plugin');
    
      const isProd = process.env.NODE_ENV === 'production'
    
      module.exports = {
        //...省略
        //配置插件
        plugins: [
          new CleanWebpackPlugin(),
    +     new HtmlWebpackPlugin({
    +       title: 'HTML页面标题', //替换index.html的title标签内容
    +       template: './public/index.html', //html模版的位置
    +     }),
        ],
        output: {
          filename: 'js/[name].[hash:8].bundle.js',
          path: path.resolve(__dirname, 'dist'),
        },
      };
    
  7. 执行命令 npm start进行打包,然后用浏览器打开 /dsit/index.html 文件,就能看到 Hello webpack。

8. 打包完成后自动打开浏览器

返回目录

  1. 需要安装的包
    包名说明环境
    webpack-dev-serverweb服务,方便开发dev
  2. 安装命令
    npm install --save-dev webpack-dev-server
    
  3. webpack.config.js
      const path = require('path');
      //...省略
    
      module.exports = {
        //...省略
        output: {
          filename: `js/[name]${isProd?'.[hash:8]':''}.bundle.js`, //出口文件
          path: path.resolve(__dirname, 'dist'),
        },
    +   devServer: {
    +     contentBase: './dist', //内容目录
    +     open: 'Google Chrome', //设置启动的浏览器
    +     port: 3000, //启动端口
    +   }
      };
    

    webpack-dev-server 编译后不写入任何输出文件。相反,它将捆绑文件保留在内存中,并像在服务器根路径上挂载的真实文件一样提供它们。如果您的页面希望在其他路径上找到捆绑文件,则可以使用 publicPath 开发服务器的配置中的选项进行更改。

  4. package.json
        {
          "name": "webpack-demo",
          "version": "1.0.0",
          "description": "",
          "main": "index.js",
          "scripts": {
            "test": "echo \"Error: no test specified\" && exit 1",
      -     "start": "cross-env NODE_ENV=development webpack --progress",
      +     "start": "cross-env NODE_ENV=development webpack-dev-server",
            "build": "cross-env NODE_ENV=production webpack --progress"
          },
          "keywords": [],
          "author": "",
          "license": "ISC",
          "devDependencies": {
            //...省略
          },
          "dependencies": {
            "@babel/runtime-corejs3": "^7.8.7"
          }
        }
    
  5. webpack5 用 webpack serve 替换 webpack-dev-server
  6. npm start打包项目,等打包完成就会打开 chrome 浏览器,看到页面了

9. 支持 React

返回目录

  1. 需要安装的包
    包名说明环境
    reactreact 主程序prod
    react-dom让 react 支持 dom 操作prod
    react-router-domreact 路由,支持 dom 操作prod
    @babel/preset-react让Babel 支持 Reactdev
  2. 安装命令
    npm i -S react react-dom react-router-dom
    npm i -D @babel/preset-react
    
  3. index.js
    - function component() {
    -   const element = document.createElement('div');
    -   element.innerHTML ='Hello webpack';
    -   return element;
    - }
    - document.body.appendChild(component());
    
    + 'use strict';
    + import React from 'react';
    + import ReactDOM from 'react-dom';
    + function Home() {
    +   return (<div>Hello, React!</div>)
    + }
    + ReactDOM.render(<Home />, document.getElementById('root'));
    
  4. index.html
      <!doctype html>
      <html>
        <head>
          <!-- 页面标题 html-webpack-plugin 插件替换 -->
          <title><%= htmlWebpackPlugin.options.title %></title>
        </head>
        <body>
    +     <div id="root"></div>
        </body>
      </html>
    
  5. .babelrc.js
      const presets = [
        "@babel/preset-env",
    +   "@babel/preset-react"
      ];
    
      const plugins = [
        [
          "@babel/plugin-transform-runtime",
          {
            "corejs": 3,
            "version": "7.8.7"
          }
        ]
      ];
    
      module.exports = { presets, plugins };
    
  6. 运行打包命令 npm start,在浏览器中看到 Hello, React! 就成功了。

10. 让 React 支持热更新

返回目录

  1. 要安装的包
    包名说明环境
    react-hot-loader让 react-dev-server 支持 React 热更新dev
    @hot-loader/react-dom消除 react-hot-loader 对 React 最新版不支持的提示dev
  2. 安装
    npm i -D react-hot-loader @hot-loader/react-dom
    
  3. index.js
      'use strict';
      import React from 'react';
      import ReactDOM from 'react-dom';
    + import { hot } from "react-hot-loader/root";
      function Home() {
        return (<div>Hello, React!</div>)
      }
    + let App = hot(Home)
    - ReactDOM.render(<Home />, document.getElementById('root'));
    + ReactDOM.render(<App />, document.getElementById('root'));
    
  4. .babelrc.js
      const presets = [
        "@babel/env",
        "@babel/preset-react"
      ];
    
      const plugins = [
        [
          "@babel/plugin-transform-runtime",
          {
            "corejs": 3,
            "version": "7.8.7"
          }
        ],
    +   "react-hot-loader/babel"
      ];
    
      module.exports = { presets, plugins };
    
  5. webpack.config.js
        const path = require('path');
        //...省略
    
        module.exports = {
        //...省略
        output: {
          filename: `js/[name]${isProd?'.[hash:8]':''}.bundle.js`, //出口文件
          path: path.resolve(__dirname, 'dist'),
        },
    +   resolve: {
    +     alias: { 'react-dom': '@hot-loader/react-dom' } //消除提示文字
    +   }
        devServer: {
          contentBase: './dist', //内容目录
          open: 'Google Chrome', //设置启动的浏览器
          port: 3000, //启动端口
    +     hot: true //支持热更新
        }
      };
    
  6. 执行打包命令 npm start,改变 index.js 中的显示内容,显示新内容就不用刷新浏览器了

11. 代码校验 ESLint

返回目录

  1. 要安装的包
    包名说明环境
    eslint主程序dev
    eslint-loaderwebpack加载器dev
    eslint-plugin-html用于检查写在 script 标签中的代码dev
    eslint-friendly-formatter报错时输出的信息格式dev
    eslint-plugin-react用于React的ESLint规则,初始化 ESLint 时会提示安装dev
  2. 安装命令
    npm i -D eslint eslint-loader eslint-friendly-formatter eslint-plugin-html eslint-plugin-react
    
  3. 在命令行中执行 eslint 命令,生成 .eslintrc.js
    npx eslint --init #或 node_modules\.bin\eslint --init
    
    #您想如何使用ESLint?
    ? How would you like to use ESLint? (Use arrow keys)
    > To check syntax, find problems
    
    #您的项目使用什么类型的模块?
    ? What type of modules does your project use? (Use arrow keys)
    > JavaScript modules (import/export)
    
    #您的项目使用哪个框架?
    ? Which framework does your project use? (Use arrow keys)
    > React
    
    #您的项目使用 typescript 吗?
    ? Does your project use TypeScript? (y/N) > n
    
    #你的代码在哪里运行?
    ? Where does your code run?
    >(*) Browser
    
    #配置文件用什么格式
    ? What format do you want your config file to be in?
    > JavaScript
    
    #是否安装 eslint-plugin-react@latest 包
    The config that you've selected requires the following dependencies:
    eslint-plugin-react@latest
    ? Would you like to install them now with npm?
    > n #上面安装了就选 no
    
  4. 修改 .eslintrc.js
      module.exports = {
          "env": {
              "browser": true,
              "es6": true
    +         'amd': true, //表示使用 amd 模块规范,支持 require
    +         'node': true, //支持node
          },
          "extends": [
              "eslint:recommended",
              "plugin:react/recommended"
          ],
          "globals": {
              "Atomics": "readonly",
              "SharedArrayBuffer": "readonly"
          },
          "parserOptions": {
              "ecmaFeatures": {
                  "jsx": true
              },
              "ecmaVersion": 2018,
              "sourceType": "module"
          },
          "plugins": [
              "react"
          ],
    +     //去掉打包时出现的 Warning: React version not specified in eslint-plugin-react settings.
    +     "settings": {
    +       "react": {
    +         "version": "detect"
    +       }
    +     },
          "rules": {
          }
      };
    
  5. webpack.config.js 参考
        const path = require('path');
        //...省略
    
        module.exports = {
        //...省略
        //配置加载器
        module: {
          rules: [
            {
              test: /\.js|jsx$/, //匹配 js 文件
              exclude: /node_modules/, //排除文件夹
              use: [
                { loader: 'babel-loader' }, //使用babel
    +           { loader: 'eslint-loader',  // eslint 加载器
    +             options: {                // eslint 选项
    +               enforce: 'pre',         //在加载前执行
    +               fix: true,              //自动修复
    +               include: [path.resolve(__dirname, 'src')], //指定检查的目录
    +               formatter: require('eslint-friendly-formatter') // 指定错误报告的格式规范
    +             }
    +           },
              ]
            },
          ]
        },
        //...省略
      };
    

12. 让 ESLint 支持 React Hook 规则

返回目录

  1. 要安装的包
    包名说明环境
    eslint-plugin-react-hooks让 ESLint 支持 React Hook 规则dev
  2. 安装命令
    npm install --save-dev eslint-plugin-react-hooks
    
  3. 修改 .eslintrc.js
      module.exports = {
          //...省略其它配置
          "plugins": [
              "react",
    +         "react-hooks"
          ],
          "rules": {
    +         "react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
    +         "react-hooks/exhaustive-deps": "warn"  // 检查 effect 的依赖
          }
      };
    

13. 在代码中判断编译环境

返回目录

  1. 使用 webpack 内置的包
    包名说明环境
    DefinePlugin构建时设置环境变量内置
  2. 规则
    每个传进 DefinePlugin 的键值都是一个标志符或者多个用 . 连接起来的标志符。
    • 如果这个值是一个字符串,它会被当作一个代码片段来使用。
    • 如果这个值不是字符串,它会被转化为字符串(包括函数)。
    • 如果这个值是一个对象,它所有的 key 会被同样的方式定义。
    • 如果在一个 key 前面加了 typeof,它会被定义为 typeof 调用。
  3. webpack.config.js
      const path = require('path');
    + const webpack = require('webpack');
      //...省略
    
      module.exports = {
        //...省略
        //配置插件
        plugins: [
    +     new webpack.DefinePlugin({
    +       PRODUCTION: JSON.stringify(true),
    +     })
        ],
        //...省略
      };
    
  4. index.js
      'use strict';
      import React from 'react';
      import ReactDOM from 'react-dom';
      import { hot } from "react-hot-loader/root";
      function Home() {
    +   /*global PRODUCTION*/ //避免eslint报错
    +   return (<div>{PRODUCTION ? "Hello, React!" : "is Development" }</div>)
      }
      let App = hot(Home)
      ReactDOM.render(<App />, document.getElementById('root'));
    

14. 加载 CSS

返回目录

  1. 要安装的包

    包名说明环境
    style-loader将处理完的 css 存在 js 中,运行时嵌入 <style>, 并挂载到 html 页面上dev
    css-loader使 webpack 可以识别 css 文件dev
  2. 安装命令

    npm install --save-dev style-loader css-loader
    
  3. webpack.config.js

      const path = require('path');
      //...省略
      
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
    +       {
    +         test: /\.css$/,
    +         use: [
    +           'style-loader',
    +           {
    +             loader: 'css-loader',
    +             options: {
    +               importLoaders: 1,
    +             }
    +           },
    +         ],
    +       },
          ],
        },
        //... 省略 plugin 设置
        //... 省略 output 设置
      };
    

    说明:

    1. webpack 使用正则表达式来确定应查找哪些文件并将其提供给特定的加载程序。所以任何以 .css 结尾的文件都将提供给 style-loader 和 css-loader。
    2. 用 import ‘./style.css’ 引入该样式的文件。当该模块运行时, 带有字符串化 CSS 的 <style> 标签将插入到 html 文件中。
    3. loader 的执行顺序是从右到左,此例是先用 css-loader 处理 css,然后在用 style-loader 把 css 插入的 html 文件中
  4. 项目中添加 style.css 文件

      webpack-demo
      |- /node_modules
      |- /src
        |- index.js
    +   |- style.css
      |- package.json
      |- webpack.config.js
      #其它文件省略...
    
  5. style.css

    .hello {
      color: red;
    }
    
  6. index.js

    + import './style.css';
      function component() {
        const element = document.createElement('div');
        element.innerHTML ='Hello webpack';
    +   element.classList.add('hello');
        return element;
      }
      document.body.appendChild(component());
    

    react 的 index,js

      'use strict';
      import React from 'react';
      import ReactDOM from 'react-dom';
    + import './style.css';
      function Home() {
    -   return (<div>Hello, React!</div>)
    +   return (<div className="hello">Hello, React!</div>)
      }
      ReactDOM.render(<Home />, document.getElementById('root'));
    
  7. 运行打包命令 npm start在浏览器中会发现 Hello webpack 变成了红色。

15. 加载图片

返回目录

  1. 要安装的包

    包名说明环境
    file-loader解析 url 方法引入的文件dev
    url-loaderLoads files as base64 encoded URLdev
  2. 安装命令

    npm install --save-dev file-loader url-loader
    
  3. webpack.config.js

      const path = require('path');
      //...省略
      
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
            {
              test: /\.css$/,
              use: [
                'style-loader',
                {
                  loader: 'css-loader',
                  options: {
                    importLoaders: 1,
                  }
                },
              ],
            },
    +       {
    +         test: /\.(png|jpg|jpeg|gif|svg)$/,
    +         use: ['file-loader'], //或者
    +         use: [
    +           {
    +             loader: 'url-loader',
    +             options: {
    +               outputPath: 'imgs/', //输出路径
    +               name: '[name]-[hash:5].[ext]', //文件名
    +               limit: 8192, //超过限制会使用file-loader
    +               esModule: false, //支持 require("imgUrl") 方式
    +             }
    +           }
    +         ]
    +       },
          ],
        },
        //...省略 plugin 设置
        //...省略 output 设置
      };
    

    说明:

    1. 当用 import MyImage from ‘./my-image.png’ 时,该图像将被处理并添加到 output 目录中,并且 MyImage 变量将包含处理后该图像的最终 url。
    2. 当使用 css-loader 时,CSS 中的 url(’./my-image.png’) 也会发生类似的过程。加载程序将识别出这是本地文件,然后将该 ‘./my-image.png’ 路径替换为 output 目录中图像的最终路径。

    说明:url-loader 会把尺寸小于8192 byte 的图片转为base64,大于的图片转给 file-loader 处理

  4. 项目中添加图片

      webpack-demo
      |- /node_modules
      |- /src
    +   |- bg.png
    +   |- icon.png
        |- index.js
        |- style.css
      |- package.json
      |- webpack.config.js
      #其它文件省略...
    
  5. style.css

      .hello {
        color: red;
      }
    + .bg {
    +   background: url('./bg.png');
    + }
    
  6. index.js

      import _ from 'lodash';
      import './style.css';
    + import Icon from './icon.png'; //引入图片
      function component() {
        const element = document.createElement('div');
        element.innerHTML ='Hello webpack';
        element.classList.add('hello');
    +   element.classList.add('bg'); //添加带图片的css
    +   const myIcon = new Image(); //添加图片到div
    +   myIcon.src = Icon;
    +   element.appendChild(myIcon);
        return element;
      }
      document.body.appendChild(component());
    

    react 的 index,js

      'use strict';
      import React from 'react';
      import ReactDOM from 'react-dom';
      import './style.css';
    + import Icon from './icon.png';
      function Home() {
    -   return (<div className="hello">Hello, React!</div>)
    +   return (<div className="bg">
    +     <div className="hello">Hello, React!</div>
    +     <img src={Icon}/>
    +   </div>)
      }
      ReactDOM.render(<Home />, document.getElementById('root'));
    
  7. 运行打包命令npm start在浏览器中会看添加的图片

16. 加载字体

返回目录

  1. webpack.config.js
      const path = require('path');
      //...省略
      
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
            //...省略 css 配置
            {
              test: /\.(png|svg|jpg|gif)$/,
              use: ['file-loader'],
            },
    +       {
    +         test: /\.(woff|woff2|eot|ttf|otf)$/,
    +         use: ['file-loader'],
    +       },
          ],
        },
        //... 省略 plugin 设置
        //... 省略 output 设置
      };
    
  2. 在项目中添加字体文件
      webpack-demo
      |- /node_modules
      |- /src
        |- bg.png
        |- icon.png
        |- index.js
    +   |- my-font.woff
    +   |- my-font.woff2
        |- style.css
      |- package.json
      |- webpack.config.js
      #其它文件省略...
    
  3. style.css
    + @font-face {
    +   font-family: 'MyFont';
    +   src:  url('./my-font.woff2') format('woff2'),
    +         url('./my-font.woff') format('woff');
    +   font-weight: 600;
    +   font-style: normal;
    + }
    
      .hello {
        color: red;
    +   font-family: 'MyFont';
      }
      .bg {
        background: url('./bg.png');
      }
    
  4. 运行打包命令npm start,在浏览器中会看到 Hello webpack 字体变了。

17. 加载数据

返回目录

数据格式:JSON、CSV、TSV 和 XML 等等
js 原生支持 JSON,可直接 import Data from ‘./data.json’; 引用。

  1. 要安装的包
    包名说明环境
    csv-loader解析 CSV、TSV 文件dev
    xml-loader解析 XML 文件dev
  2. 安装命令
    npm install --save-dev csv-loader xml-loader
    
  3. webpack.config.js
      const path = require('path');
      //...省略
      
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
            //...省略 css 配置
            //...省略 图片 配置
            {
              test: /\.(woff|woff2|eot|ttf|otf)$/,
              use: ['file-loader'],
            },
    +       {
    +         test: /\.(csv|tsv)$/,
    +         use: ['csv-loader'],
    +       },
    +       {
    +         test: /\.xml$/,
    +         use: ['xml-loader'],
    +       },
          ],
        },
        //... 省略 plugin 设置
        //... 省略 output 设置
    
  4. 在项目中添加 xml 文件
      webpack-demo
      |- /node_modules
      |- /src
        |- bg.png
    +   |- data.xml
        |- icon.png
        |- index.js
        |- my-font.woff
        |- my-font.woff2
        |- style.css
      |- package.json
      |- webpack.config.js
      #其它文件省略...
    
  5. data.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <note>
      <to>Mary</to>
      <from>John</from>
      <heading>Reminder</heading>
      <body>Call Cindy on Tuesday</body>
    </note>
    
    用 import 可以引入JSON、CSV、TSV 和 XML 这四种数据类型
  6. index.js
      import './style.css';
      import Icon from './icon.png';
    + import Data from './data.xml'; //引入数据
      function component() {
        const element = document.createElement('div');
        element.innerHTML = 'Hello webpack';
        element.classList.add('hello');
        element.classList.add('bg');
        const myIcon = new Image();
        myIcon.src = Icon;
        element.appendChild(myIcon);
    +   console.log(Data); //输出数据
        return element;
      }
      document.body.appendChild(component());
    
    react 同上
  7. 运行打包命令 npm start,在浏览器中的控制台(cosole)中能看到加载的数据。

18. 加载音频

返回目录

  1. 要安装的包
    包名说明环境
    url-loaderLoads files as base64 encoded URLdev
  2. 安装命令
    npm install --save-dev url-loader
    
  3. webpack.config.js
      const path = require('path');
      //...省略
      
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
            //...省略 css 配置
            //...省略 图片 配置
            //...省略 字体 配置
            //...省略 csv|tsv 配置
            {
              test: /\.xml$/,
              use: ['xml-loader'],
            },
    +       {
    +         test: /\.(mp3)(\?.*)?$/,
    +         loader: 'url-loader',
    +         options: {
    +           name:'audios/[name].[ext]',
    +           limit:10
    +         }
    +       }
          ],
        },
        //... 省略 plugin 设置
        //... 省略 output 设置
    
  4. 在项目中添加音频文件
      webpack-demo
      |- /node_modules
      |- /src
    +   |- alarm.mp3
        |- bg.png
        |- data.xml
        |- icon.png
        |- index.js
        |- my-font.woff
        |- my-font.woff2
        |- style.css
      |- package.json
      |- webpack.config.js
      #其它文件省略...
    
  5. index.js
      import './style.css';
      import Icon from './icon.png';
      import Data from './data.xml';
    + import Mp3 from './alarm.mp3';
      function component() {
        const element = document.createElement('div');
        element.innerHTML = 'Hello, webpack';
        element.classList.add('hello');
        const myIcon = new Image();
        myIcon.src = Icon;
        element.appendChild(myIcon);
        
    +   const myMp3 = new Audio();
    +   myMp3.src = Mp3;
    +   myMp3.loop = true;
    +   element.appendChild(myMp3);
    +   var inputElement = document.createElement('input');  
    +   inputElement.type = "button";
    +   inputElement.value = "播放";  
    +   inputElement.onclick = () =>{
    +     myMp3.play();
    +   }
    +   element.appendChild(inputElement); 
        
        console.log(Data);
        return element;
      }
      document.body.appendChild(component());
    
    react 的 index.js
      'use strict';
    - import React from 'react';
    + import React, { useState } from 'react'; 
      import ReactDOM from 'react-dom';
      import './style.css';
      import Icon from './icon.png';
    + import Mp3 from './alarm.mp3';
      function Home() {
    +   let [ audio ] = useState(0);
        return (<div className="bg">
          <div className="hello">Hello, React!</div>
          <img src={Icon}/>
    +     <audio src={Mp3} ref={(input)=>{audio = input}} />
    +     <input type="button" value="播放" onClick={()=>{
    +       audio && audio.play(); //点击按钮播放音频
    +     }}/>
        </div>)
      }
      ReactDOM.render(<Home />, document.getElementById('root'));
    
  6. 运行打包命令npm start在浏览器中点击播放按钮播放声音。

19. CSS 分离

返回目录

  1. 要安装的包
    包名说明环境
    extract-text-webpack-plugin分离css,支持webpack1/2/3dev
    mini-css-extract-plugin分离css,官方推荐,几个月不更新了dev
    extract-css-chunks-webpack-plugin分离css,一直在更新dev

19.1. mini-css-extract-plugin

返回目录

  1. 安装
    npm i -D mini-css-extract-plugin
    
  2. webpack.config.js
      const path = require('path');
      //...省略
    + const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
            {
              test: /\.css$/,
              use: [
    -           'style-loader',
    +           {
    +             loader: MiniCssExtractPlugin.loader,
    +             options: {
    +               publicPath: '../',  //防止css中图片路径错误
    +               hmr: process.env.NODE_ENV === 'development',
    +               reloadAll: true
    +             },
    +           },
                {
                  loader: 'css-loader',
                  options: {
                    importLoaders: 1,
                  }
                },
              ],
            },
            //...省略
          ],
        },
        plugins: [
    +     new MiniCssExtractPlugin({
    +       filename: `css/[name]${isProd ? '.[contenthash:8]':''}.css`,
    +       chunkFilename: `css/[id]${isProd ? '.[contenthash:8]':''}.css`,
    +       ignoreOrder: false,
    +     }),
        ],
        //... 省略 output 设置
    

19.2. extract-css-chunks-webpack-plugin

返回目录

  1. 安装
    npm i -D extract-css-chunks-webpack-plugin
    
  2. 修改 webpack.config.js
      const path = require('path');
      //...省略
    + const ExtractCssChunks = require("extract-css-chunks-webpack-plugin");
    
      module.exports = {
        //...省略
        module: {
          rules: [
            //...省略 js 配置
            {
              test: /\.css$/,
              use: [
    -           'style-loader',
    +           {
    +             loader: ExtractCssChunks.loader,
    +             options: {
    +               hmr: process.env.NODE_ENV === 'development',
    +               reloadAll: true
    +             },
    +           },
                {
                  loader: 'css-loader',
                  options: {
                    importLoaders: 1,
                  }
                },
              ],
            },
            //...省略
          ],
        },
        plugins: [
    +     new ExtractCssChunks({
    +       filename: `css/[name]${isProd ? '.[contenthash:8]':''}.css`,
    +       chunkFilename: `css/[id]${isProd ? '.[contenthash:8]':''}.css`,
    +       orderWarning: true,
    +     }),
        ],
        //... 省略 output 设置
      }
    

20. CSS Module

返回目录

  1. 修改 webpack.config.js
      //...省略
      module.exports = {
        //省略....
        module: {
          rules: [
            //..,省略 js 配置
            {
              test: /\.css$/,
    +         exclude: [/node_modules/, /\.module\.css$/], //排除css模块
              use: [
                {
                  loader: MiniCssExtractPlugin.loader,
                  options: {
                    hmr: process.env.NODE_ENV === 'development',
                    reloadAll: true
                  },
                },
                {
                  loader: 'css-loader',
                  options: {
                    importLoaders: 1,
                  }
                },
              ],
            },
    +       {
    +         test: /\.module\.css$/,
    +         exclude: /node_modules/,
    +         use: [
    +           {
    +             loader: MiniCssExtractPlugin.loader,
    +             options: {
    +               hmr: process.env.NODE_ENV === 'development',
    +               reloadAll: true,
    +             }
    +           },
    +           {
    +             loader: 'css-loader',
    +             options: {
    +               importLoaders: 1,
    +               modules: {
    +                 localIdentName: '[path][name]__[local]--[hash:base64:5]'
    +               },
    +             }
    +           },
    +         ]
    +       },
    		//....省略
          ]
        },
        //...省略 plugin 配置
        //...省略 output 配置
      }
    
  2. style.module.css
    .world {
      color: blue;
    }
    
  3. index.js
      import React from 'react';
      import './style.css';
    + import css from './style.module.css';
    
      function Home() {
        return (<div className="bg">
          <div className="hello">Hello, React!</div>
    +     <div className={css.world}>I am World!</div>
          <img src={Icon}/>
          <audio src={Mp3} ref={(input)=>{audio = input}} />
          <input type="button" value="播放" onClick={()=>{
            audio && audio.play(); //点击按钮播放音频
          }}/>
        </div>)
      }
    
      export default Home;
    

21. PostCSS 处理 CSS 压缩/去重/自动前缀转换

返回目录

  1. 要安装的包
    包名说明环境
    postcss-loaderpostcss 加载器dev
    precss支持现代 CSS 语法(SASS,SCSS)
    包含 postcss-preset-env 转换为浏览器识别的 CSS
    包含 Autoprefixer 自动添加(浏览器)前缀
    dev
    cssnanocss 优化处理,压缩去重dev
    postcss-scss解析 SCSS 语法dev
    postcss-calc在编译阶段进行计算dev
    postcss-import转换 @import 规则 用于内联内容dev
    postcss-normalize提取 normalize.css 中支持浏览器的部分(去重)dev
    normalize.css标准 css,让各个浏览器的默认标签显示一致dev
    postcss-plugin-px2rempx 转 remdev
  2. 安装命令
    npm i -D postcss-loader precss cssnano postcss-import postcss-scss postcss-calc postcss-plugin-px2rem postcss-normalize normalize.css
    
  3. 新建 postcss.config.js
      |- /node_modules
      |- /src
        |- index.js
        |- style.css
      |- .babelrc.js
      |- .eslintrc.js
      |- package.json
    + |- postcss.config.js
      |- webpack.config.js
    
  4. postcss.config.js
    module.exports = ({ file, options, env }) => ({
      parser: require('postcss-scss'),
      plugins: [
        require('postcss-import'),
        require('postcss-normalize')({
          forceImport:true, //强制插入
          browsers: 'last 2 versions' //浏览器近2个版本,根据需求改变
        }),
        //支持“现代css”(Sass,Scss)语法,并转成 css
        require('precss'),
        //编译前计算
        require('postcss-calc'),
        //px 转 rem
        require('postcss-plugin-px2rem')({ rootValue: 100, minPixelValue: 2 }),
      //压缩css,去除所有注释
        require('cssnano')({
          preset: ['default', { discardComments: { removeAll: true } }]
        })
      ]
    });
    
  5. webpack.config.js
      //...省略
      module.exports = {
        //省略....
        module: {
          rules: [
            //..,省略 js 配置
            {
              test: /\.css$/,
              exclude: [/node_modules/, /\.module\.css$/], //排除css模块
              use: [
                {
                  loader: MiniCssExtractPlugin.loader,
                  options: {
                    hmr: process.env.NODE_ENV === 'development',
                    reloadAll: true
                  },
                },
                {
                  loader: 'css-loader',
                  options: {
                    importLoaders: 1,
                  }
                },
    +           'postcss-loader'
              ],
            },
            {
              test: /\.module\.css$/,
              exclude: /node_modules/,
              use: [
                {
                  loader: MiniCssExtractPlugin.loader,
                  options: {
                    hmr: process.env.NODE_ENV === 'development',
                    reloadAll: true,
                  }
                },
                {
                  loader: 'css-loader',
                  options: {
                    importLoaders: 1,
                    modules: {
                      localIdentName: '[path][name]__[local]--[hash:base64:5]'
                    },
                  }
                },
    +           'postcss-loader'
              ]
            }
          ]
        },
        //...省略 plugin 配置
        //...省略 output 配置
      }
    

22. 公共资源拆分

返回目录
SplitChunksPlugin 是 webpack 内置模块

  1. webpack.config.js
      const path = require('path');
      //...省略
    
      module.exports = {
        //...省略
        output: {
          filename: `js/[name]${isProd?'.[hash:8]':''}.bundle.js`, //出口文件
          path: path.resolve(__dirname, 'dist'),
        },
    +   optimization: {
    +     splitChunks: {
    +       chunks: 'all',
    +     },
    +   },
      };
    
    点击查看更多关于 SplitChunksPlugin
  2. 运行打包命令 npm start
    有了 optimization.splitChunks 配置选项后,可以看到从 index.bundle.js 和 another.bundle.js 中删除了重复的依赖代码,并将 lodash 分离为一个单独的文件。

23. 动态(按需)加载

返回目录
当涉及动态代码拆分时,webpack支持两种类似的技术。
第一是用符合 ECMAScript 建议的 import() 语法;
第二是用 Webpack 的传统方法 require.ensure。推荐使用。

23.1 ECMAScript 建议的 import 方法

返回目录

  1. index.js
    使用动态导入来分离 lodash 模块
    function getComponent() {
      const element = document.createElement('div');
    
      return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => {
        const element = document.createElement('div');
        element.innerHTML = _.join(['Hello', 'webpack'], ' ');
        return element;
      }).catch(error => 'An error occurred while loading the component');
    }
    
    getComponent().then(component => {
      document.body.appendChild(component);
    })
    
    也可以与 async 一起使用,前提是安装 @babel/plugin-syntax-dynamic-import包。
  2. webpackPrefetch 预取:将来可能需要一些资源
    import(/* webpackPrefetch: true */ 'LoginModal');
    
  3. webpackPreload 预加载:当前期间可能需要资源
    import(/* webpackPreload: true */ 'ChartingLibrary');
    
    • 预加载的块开始并行于父块加载。父块完成加载后,将开始预提取块。
    • 预加载的块具有中等优先级,可以立即下载。浏览器空闲时,将下载预提取的块。
    • 父块应立即请求预加载的块。预取的块可以在将来的任何时候使用。
    • 浏览器支持不同。

23.2 webpack 的 require.ensure 方法

返回目录
webpack 的遗留功能

  1. 代码
    // 空参数
    require.ensure([], function(require){
        var = require('module-b');
    });
    
    // 依赖模块 "module-a", "module-b",会和'module-c'打包成一个chunk来加载
    // 不同的分割点可以使用同一个chunkname,这样可以保证不同分割点的代码模块打包为一个chunk
    require.ensure(["module-a", "module-b"], function(require) {
      var a = require("module-a");
      var b = require("module-b");
      var c = require('module-c');
    },"custom-chunk-name");
    

23.3 bundle-loader

返回目录
用于分离代码和延迟加载生成的 bundle

// 在require bundle时,浏览器会立即加载
var waitForChunk = require("bundle!./file.js");
 
// 使用lazy模式,浏览器并不立即加载,只在调用wrapper函数才加载
var waitForChunk = require("bundle?lazy!./file.js");
 
// 等待加载,在回调中使用
waitForChunk(function(file) {
  var file = require("./file.js");
});

默认普通模式wrapper:

var cbs = [],data;
module.exports = function(cb) {
  if(cbs) cbs.push(cb);
  else cb(data);
},
require.ensure([], function(require) {
  data = require('./file.js');
  var callbacks = cbs;
  cbs = null;
  for(var i = 0, l = callbacks.length; i < l; i++) {
    callbacks[i](data);
  }
});

lazy模式wrapper:

module.exports = function (cb) {
  require.ensure([], function(require) {
    var app = require('./file.js');
    cb(app);
  });
};

使用 bundle-loader 在代码中 require 文件的时候只是引入了 wrapper 函数,而且因为每个文件都会产生一个分离点,导致产生了多个打包文件,而打包文件的载入只有在条件命中的情况下才产生,也就可以按需加载。

  • 支持自定义Chunk名称:
    require("bundle-loader?lazy&name=my-chunk!./file.js");
    

23.4 promise-loader

返回目录
类似于 bundle-loader ,但是使用了 promise API

// 使用Bluebird promise库
var load = require("promise?bluebird!./file.js");

// 使用全局Promise对象
var load = require("promise?global!./file.js");

load().then(function(file) {

});

wrapper函数:

var Promise = require('bluebird');

module.exports = function (namespace) {
  return new Promise(function (resolve) {
    require.ensure([], function (require) {
      resolve(require('./file.js')[namespace]));
    });
  });
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值