Webpack資源管理

guitar_zp發表於2017-06-14

資源管理

提示:

  1. 版本問題

本文基於 webpack 2.x 版本。webpack 2.x 相比 webpack 1.x 有重大改變。所以,如果你的專案中已使用了 webpack 1.x ,本教程的示例將不適用,請慎重。

如果鐵了心要升級 webpack ,請參考 webpack 官方文件 – 從 v1 遷移到 v2

  1. 閱讀建議

閱讀本文前,建議先閱讀 Webpack 概念

webpack 的優勢

webpack 最重要的功能就是資源管理。

JavaScript 世界已有好幾個有名的資源管理工具,webpack 有什麼獨到之處呢?

webpack 出現之前,前端開發人員會使用 gruntgulp 等工具來處理這些 web 資源,如樣式檔案(例如 .css.less.sass),圖片(例如 .png.jpg.svg),字型(例如 .woff.woff2.eot)和資料(例如 .json.xml.csv)等,並將它們從 /src 資料夾移動到 /dist 或 /build 目錄中。

而 webpack 從 entry(入口) 開始,訪問應用程式,並動態打包(dynamically bundle)所有依賴項。這是極好的創舉,因為現在每個模組都可以明確表述它自身的依賴,這可以避免打包未使用的模組。

Loader

Loader(載入器) 用於對模組的原始碼進行轉換。

使用載入器一般遵循幾步:

  1. 安裝載入器
  2. 配置 Loader
  3. 引用資原始檔

安裝載入器

根據需要載入的資原始檔,選擇下載對應的載入器。

$ npm install --save-dev css-loader

更多 webpack 可用Loader 請檢視:webpack loaders

配置 Loader

​️ 注意:

webpack 2.x 版本的 Loader 配置和 webpack 1.x 版本差別很大。

Loader 在 webpack.config.js 檔案的 module 屬性中配置。

資源型別對應單一載入器

module: {
  rules: [
    {test: /.css$/, loader: `css-loader`}
  ]
},

資源型別對應多個載入器

module: {
  rules: [
    {
      test: /.css$/,
      use: ["style-loader", "css-loader"]
    }
  ]
},

載入器含配置選項

module: {
  rules: [
    {
      test: /.css$/,
      use: [
        { loader: `style-loader` },
        {
          loader: `css-loader`,
          options: {
            modules: true
          }
        }
      ]
    }
  ]
},

引用資原始檔

完成上兩步後,就可以在 JavaScript 中使用 importrequire 關鍵字引用相應型別資原始檔。

import `./index.css`;
require(`./index.css`);

Plugin

Plugin(外掛) 用於解決 Loader 無法解決的問題,它是 Loader 的輔助。

由於 plugin 可以攜帶引數/選項,你必須在 wepback 配置中,向 plugins 屬性傳入 new 例項。

安裝外掛

webpack 自身包含了一些常用外掛,你可以通過 webpack 來引用。除此之外的外掛,使用前需要安裝

$ npm install --save-dev html-webpack-plugin OpenBrowserPlugin

更多 webpack Plugins 可以檢視: webpack plugins

配置 Plugin

const webpack = require(`webpack`);
const HtmlWebpackPlugin = require(`html-webpack-plugin`);
const OpenBrowserPlugin = require(`open-browser-webpack-plugin`);

module.exports = {
  // 附加外掛列表
  plugins: [
    // 壓縮 js 外掛
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),

    // 用於簡化 HTML 檔案(index.html)的建立,提供訪問 bundle 的服務。
    new HtmlWebpackPlugin({
      title: "react-step-by-step",
      template: "./index.html"
    }),

    // 自動開啟瀏覽器
    new OpenBrowserPlugin({
      url: "http://localhost:8080"
    })
  ]
};

載入資源專題

載入 React

很多瀏覽器並不識別 React 語法,為了讓瀏覽器支援,你需要使用 babel-loader 直譯器來轉義 React 語法為普通的 Javascript 語法。

注意:

官方推薦 babel-loader 和 webpack 的對應版本

webpack 1.x | babel-loader <= 6.x

webpack 2.x | babel-loader >= 7.x (推薦)(^6.2.10 也可以執行,但會有不贊成的警告(deprecation warnings))

首先,安裝需要使用的庫:

$ npm install --save-dev babel-loader babel-preset-es2015 babel-preset-react

babel-preset-xxx 表示你希望轉義的語法。

webpack.config.js 中的模組配置如下:

// 關於模組配置
module: {

  // 模組規則(配置 loader、解析器等選項)
  rules: [
    // 這裡是匹配條件,每個選項都接收一個正規表示式或字串
    // test 和 include 具有相同的作用,都是必須匹配選項
    // exclude 是必不匹配選項(優先於 test 和 include)
    // 最佳實踐:
    // - 只在 test 和 檔名匹配 中使用正規表示式
    // - 在 include 和 exclude 中使用絕對路徑陣列
    // - 儘量避免 exclude,更傾向於使用 include
    {
      // 語義直譯器,將 js/jsx 檔案中的 es2015/react 語法自動轉為瀏覽器可識別的 Javascript 語法
      test: /.jsx?$/,
      include: path.resolve(__dirname, "app"),

      // 應該應用的 loader,它相對上下文解析
      // 為了更清晰,`-loader` 字尾在 webpack 2 中不再是可選的
      // 檢視 webpack 1 升級指南。
      loader: "babel-loader",

      // loader 的可選項
      options: {
        presets: ["es2015", "react"]
      },
    },
  ]
},

示例DEMO04: (DEMO / SOURCE)

載入 CSS

為了從 JavaScript 模組中 import 一個 CSS 檔案,你只需要在 module 中安裝並新增 style-loader 和 css-loader

$ npm install --save-dev style-loader css-loader

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          `css-loader`,
          `style-loader`
        ]
      }
    ]
  },
  //...
}

好了,此時你就可以在程式碼中通過 import `./style.css` 的方式引入 CSS 檔案。

其餘,載入 less,sass 等樣式檔案也是大同小異,不一一細說。

示例DEMO06: (DEMO / SOURCE)

載入圖片

如何打包、載入圖片呢?你可以使用 file-loader來指定要載入的圖片。

$ npm install --save-dev file-loader

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /.(png|svg|jpg|gif)$/,
        use: [
          `file-loader`
        ]
      }
    ]
  },
  //...
}

然後,你可以通過 import imgBig from `./lion.png` 的方式引入圖片。例:

import React from `react`;
import imgBig from `./lion.png`;

class Welcome extends React.PureComponent {
  render() {
    return (
      <div>
        <h1>Hello, {this.props.name}</h1>
        <img src={imgBig} />
      </div>
    );
  }
}
export default Welcome;

壓縮圖片

這還不算完,日常開發中,經常會遇到有些圖片檔案過大的問題,這會影響你的 app 的載入速度。webpack 提供了壓縮圖片的方法幫你解決圖片大的問題。

首先,你需要安裝 image-webpack-loader

$ npm i --save-dev image-webpack-loader

接下來,修改 webpack.config.js

{
  // 圖片載入 + 圖片壓縮
  test: /.(png|svg|jpg|gif)$/,
  loaders: [
    "file-loader",
    {
      loader: "image-webpack-loader",
      query: {
        progressive: true,
        pngquant: {
          quality: "65-90",
          speed: 4
        }
      }
    }
  ]
}

示例DEMO07: (DEMO / SOURCE)

載入字型

那麼,像字型這樣的其他資源如何處理呢?file-loader 和 url-loader 可以接收並載入任何檔案,然後將其輸出到構建目錄。這就是說,我們可以將它們用於任何型別的檔案,包括字型:

webpack.config.js

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /.(woff|woff2|eot|ttf|svg)$/,
        use: [
          `file-loader`
        ]
      }
    ]
  },
  //...
}

一切就緒後,你可以在 css 檔案中這樣引入字型:

@font-face {
  font-family: `MyDiyFont`;
  src: url(`./font/iconfont.eot`); /* IE9*/
  src: url(`./font/iconfont.eot?#iefix`) format(`embedded-opentype`), /* IE6-IE8 */
  url(`./font/iconfont.woff`) format(`woff`), /* chrome、firefox */
  url(`./font/iconfont.ttf`) format(`truetype`), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
  url(`./font/iconfont.svg#iconfont`) format(`svg`); /* iOS 4.1- */
}

h1 {
  font-family: `MyDiyFont`;
  font-size: 24px;
}

p {
  font-family: `MyDiyFont`;
  font-size: 18px;
}

然後,相對路徑,會被替換為構建目錄中的完整路徑/檔名。

示例DEMO08: (DEMO / SOURCE)

Webpack 系列教程

歡迎閱讀其它內容:


相關文章