webpack 配置彙總


1. webpack 介紹

返回目錄
webpack 是用於打包 JavaScript 項目的。可以在 cli (命令行) 和 API 中調用其接口。

2. 安裝 Webpack

返回目錄

  1. 要安裝的包
    包名 說明 環境
    webpack webpack 主程序 dev
    webpack-cli webpack 命令行工具 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"
        }
      }
    
  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-loader Babel 加載器 dev
    @babel/core Babel 核心包 dev
    @babel/cli Bable 命令行 dev
    @babel/preset-env 根據配置的目標瀏覽器或運行環境,自動的將代碼轉爲 es5 dev
    @babel/plugin-transform-runtime generator、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 自動修改的 html dev
  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-server web服務,方便開發 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. npm start打包項目,等打包完成就會打開 chrome 瀏覽器,看到頁面了

9. 支持 React

返回目錄

  1. 需要安裝的包
    包名 說明 環境
    react react 主程序 prod
    react-dom 讓 react 支持 dom 操作 prod
    react-router-dom react 路由,支持 dom 操作 prod
    @babel/preset-react 讓Babel 支持 React dev
  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-loader webpack加載器 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?
    > Yes #上面安裝了就選 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"
          ],
          "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');
      //...省略
    
      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.common.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.common.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-loader Loads files as base64 encoded URL dev
  2. 安裝命令

    npm install --save-dev file-loader url-loader
    
  3. webpack.common.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.common.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.common.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.common.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.common.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.common.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-loader Loads files as base64 encoded URL dev
  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.common.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/3 dev
    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: {
    +               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.common.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>
          <ul>
            <!-- 全局 css -->
            <li className="hello">Hello, World!</li>
            <!-- css module -->
    +       <li className={css.world}>I am Test!</li>
          </ul>
        </div>)
      }
    
    export default Home;
    

21. PostCSS 處理 CSS 壓縮/去重/自動前綴轉換

返回目錄

  1. 要安裝的包
    包名 說明 環境
    postcss-loader postcss 加載器 dev
    precss 支持現代 CSS 語法(SASS,SCSS)
    包含 postcss-preset-env 轉換爲瀏覽器識別的 CSS
    包含 Autoprefixer 自動添加(瀏覽器)前綴
    dev
    cssnano css 優化處理,壓縮去重 dev
    postcss-scss 解析 SCSS 語法 dev
    postcss-calc 在編譯階段進行計算 dev
    postcss-import 轉換 @import 規則 用於內聯內容 dev
    postcss-normalize 提取 normalize.css 中支持瀏覽器的部分(去重) dev
    normalize.css 標準 css,讓各個瀏覽器的默認標籤顯示一致 dev
    postcss-plugin-px2rem px 轉 rem dev
  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]));
    });
  });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章