webpack 之 管理資源

上一篇筆記整理了整合JS資源的過程,現(xiàn)在我們嘗試整合一些其他資源

在 webpack 出現(xiàn)之前,前端開發(fā)人員會(huì)使用 grunt 和 gulp 等工具來處理資源,并將它們從 /src 文件夾移動(dòng)到 /dist/build 目錄中。

同樣的方式也被用于 JS 模塊,但是像 webpack 這樣的工具,將動(dòng)態(tài)打包(dynamically bundle)所有依賴項(xiàng)(創(chuàng)建所謂的依賴圖(dependency graph))。這是極好的創(chuàng)舉,因?yàn)楝F(xiàn)在每個(gè)模塊都可以明確表述它自身的依賴,我們將避免打包未使用的模塊。

webpack 最出色的功能之一就是,除了 JavaScript,還可以通過 loader 引入任何其他類型的文件。也就是說,以上列出的那些 JavaScript 的優(yōu)點(diǎn)(例如顯式依賴),同樣可以用來構(gòu)建網(wǎng)站或 web 應(yīng)用程序中的所有非 JavaScript 內(nèi)容。讓我們從 CSS 開始起步,或許你可能已經(jīng)熟悉了這個(gè)設(shè)置過程。

安裝以及加載 CSS

為了從 JS 模塊中 import 一個(gè) CSS 文件,需要在 module 配置中安裝并添加 style-loadercss-loader

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

并在 webpack.config.fs 文件中添加一個(gè)模塊規(guī)則

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
    },
    // 文件中添加下面的代碼
    module: {
        rules: [
            {
                // 每次遇到 require 或 import 時(shí)進(jìn)行檢測
                test: /\.css$/,
                // 如果是 .css 后綴的文件,則用下面兩個(gè) loader 去處理
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
};

webpack 根據(jù)正則表達(dá)式,來確定應(yīng)該查找哪些文件,并將其提供給指定的 loader。上面的這種情況,以 .css 結(jié)尾的全部文件,都將被提供給 style-loadercss-loader。

這樣就可以在依賴于此樣式的文件中 import './style.css'。然后,當(dāng)該模塊運(yùn)行時(shí),含有 CSS 字符串的 <style> 標(biāo)簽,將被插入到 html 文件中的 <head> 中。

我想如果理解了上篇 JS 整合的方法,這里應(yīng)該也不難,如果你覺得應(yīng)該看看詳細(xì)的過程,請?jiān)L問管理資源 | webpack

需要注意的是,多數(shù)情況下,也可以進(jìn)行 CSS 分離,以便在生產(chǎn)環(huán)境中節(jié)省加載時(shí)間。最重要的是,現(xiàn)有的 loader 可以支持任何你可以想到的 css 處理器風(fēng)格 - postcss , sass 和 less 等。

加載圖片

上述的過程做到了 CSS 的加載,但是我們的背景和圖標(biāo)這些圖片要怎么去處理呢?這就要用到另一個(gè) loader 了(file-loader),可以通過它輕松地將這些內(nèi)容混合到 CSS 中:

npm install --save-dev file-loader

當(dāng)然我們同樣要修改我們的 webpack.config.js

const path = require('path');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
            ]
        },
          {
            test: /\.(png|svg|jpg|gif)$/,
            use: [
              'file-loader'
            ]
          }
      ]
    }
};

當(dāng)在 JS 文件中 import img from './img.png',該圖像將被處理并添加到 output 目錄,并且 img 變量將包含該圖像在處理后的最終 url。當(dāng)使用 css-loader 時(shí),如上所示,你的 CSS 中的 url('./img.png') 會(huì)使用類似的過程去處理。loader 會(huì)識(shí)別這是一個(gè)本地文件,并將 './img.png' 路徑替換輸出 目錄中圖像的最終路徑。html-loader 以相同的方式處理 <img src="./img.png" />。

詳細(xì)的過程,請?jiān)L問 管理資源 | webpack

合乎邏輯的下一步是:壓縮和優(yōu)化你的圖像。查閱 image-webpack-loaderurl-loader,以了解更多關(guān)于增強(qiáng)加載處理圖片功能。

加載字體

處理完了圖像,那么像字體這樣的其他資源如何處理呢?file-loaderurl-loader 可以接受并加載任何文件,然后將其輸出到構(gòu)建目錄。

更新 webpack.config.js ,在 rules 里加入

{
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    use: [
        'file-loader'
    ]
}

然后再項(xiàng)目中添加一些字體文件 ./src/my-font.woff 或者 ./src/my-font.woff2

通過配置好 loader 并將字體文件放在合適的地方,可以通過一個(gè) @font-face 聲明引入。本地的 url(...) 指令會(huì)被 webpack 獲取處理,跟處理圖片資源一樣。

src/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;
}

body {
    font-family: 'MyFont';
}

加載數(shù)據(jù)

數(shù)據(jù)也是可以加載的有用資源,如:JSON 文件、CSV、TSV 和 XML。類似于 NodeJS,JSON 支持實(shí)際上是內(nèi)置的,也就是說 import Data from './data.json' 默認(rèn)將正常運(yùn)行。要導(dǎo)入 CSV、TSV 和 XML,你可以使用 csv-loaderxml-loader。

npm install --save-dev csv-loader xml-loader

同樣需要更新 webpack.config.js ,在 rules 里加入

{
  test: /\.(csv|tsv)$/,
  use: [
    'csv-loader'
  ]
},
{
  test: /\.xml$/,
  use: [
    'xml-loader'
  ]
}

可以 import 這四種類型的數(shù)據(jù)(JSON, CSV, TSV, XML)中的任何一種,所導(dǎo)入的 Data 變量將包含可直接使用的已解析 JSON

import Data from './data.xml'

全局資源

|——/components
  |——/my-component
    |——index.js
    |——index.css
    |——icon.svg
    |——img.png

這種配置方式會(huì)使你的代碼更具備可移植性,因?yàn)楝F(xiàn)有的統(tǒng)一放置的方式會(huì)造成所有資源緊密耦合在一起。假如你想在另一個(gè)項(xiàng)目中使用 /my-component,只需將其復(fù)制或移動(dòng)到 /components 目錄下。只要你已經(jīng)安裝了任何擴(kuò)展依賴(external dependencies),并且你已經(jīng)在配置中定義過相同的 loader,那么項(xiàng)目應(yīng)該能夠良好運(yùn)行

管理輸出

目前為止,我們在 index.html 文件中手動(dòng)引入所有資源,然而隨著應(yīng)用程序增長,并且一旦開始對文件名使用哈希并輸出多個(gè)bundle/main,手動(dòng)對 index.html 文件進(jìn)行處理,一切就會(huì)變得困難起來。

這個(gè)時(shí)候,我們可以通過一些插件,使這個(gè)過程更容易操控。

準(zhǔn)備

首先,讓我們重新調(diào)整一下我們的項(xiàng)目

webpack-demo
|——package.json
|——webpack.config.fs
|——/dist
|——/src
  |——index.js
  |——print.js   // 新增  
|——/node_modules

我們在 src/print.js 文件中添加一些測試邏輯

src/print.js

export.default function printMe() {
    console.log('I get called from print.js')
}

并且在 src/index.js 文件中使用這個(gè)函數(shù)

src/index.js

import $ from 'jquery'
import printMe from './print.js'

$('body').on('click', printMe)
$('body').append('<h1>Kofe Chen</h1>')

同時(shí),我們還要更新 dist/index.html 文件,來為 webpack 分離入口做好準(zhǔn)備

dist/index.html

<!doctype html>
<html>
  <head>
     <title>Output Management</title>
     <script src="./print.bundle.js"></script>
  </head>
  <body>
     <script src="./app.bundle.js"></script>
  </body>
</html>

最后調(diào)整配置,在 entry 添加 src/print.js 作為新的入口起點(diǎn)( print ),然后修改 output,一遍根據(jù)入口名稱動(dòng)態(tài)生成 bundle 名稱:

webpack.config.js

const path = require('path');

module.exports = {
  entry: {
    app: './src/index.js',
    print: './src/print.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

執(zhí)行的時(shí)候,如果存在 webpack.config.js 配置文件,webpack 命令將會(huì)默認(rèn)選擇使用它。

webpack 生成了 print.bundle.jsapp.bundle.js 文件,這也和我們在 index.html 文件中指定的文件名稱相對應(yīng)。

但是,如果我們更改了一個(gè)入口起點(diǎn)的名稱,甚至添加了一個(gè)新的名稱,生成的包將被重命名在一個(gè)構(gòu)建中,可原本的 index.html 文件仍然會(huì)引用舊的名字。那么我們就需要用 HtmlWebpackPlugin 來解決這個(gè)問題。

設(shè)定 HtmlWebpackPlugin

首先安裝插件,并且調(diào)整 webpack.config.js 文件

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

webpack.config.js

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

module.exports = {
  entry: {
    app: './src/index.js',
    print: './src/print.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Output Management' 
    })
  ],
  output: {
    filename: '[name].main.js',
    path: path.resolve(__dirname, 'dist')
  }
};

在構(gòu)建之前,我們應(yīng)該了解的是:雖然在 dist/ 文件夾中已經(jīng)有了 index.html 這個(gè)文件,然后 HtmlWebpackPlugin 還是會(huì)默認(rèn)生成 index.html 文件。也就是說,HtmlWebpackPlugin 會(huì)用新生成的 index.html 文件把我們原來創(chuàng)建的替換掉。

如果想要了解更多 HtmlWebpackPlugin 插件提供的全部功能和選項(xiàng),可以訪問 HtmlWebpackPlugin

你還可以看一下 html-webpack-template,除了默認(rèn)模板之外,還提供了一些額外的功能。

清理 /dist 文件夾

webpack 會(huì)生成文件,然后將這些文件放置在 /dist 文件夾中,但是 webpack 無法追蹤到哪些文件是實(shí)際在項(xiàng)目中用到的。

通常,在每次構(gòu)建前清理 /dist 文件夾,是比較推薦的做法,因此只會(huì)生成用到的文件。

clean-webpack-plugin 是一個(gè)比較普及的管理插件

npm install clean-webpack-plugin --save-dev

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  entry: {
    app: './src/index.js',
    print: './src/print.js'
  },
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
      title: 'Development'
    })
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

現(xiàn)在執(zhí)行 npm run build,再檢查 /dist 文件夾,如果順利,應(yīng)該不會(huì)再看到舊的文件,只有構(gòu)建后生成的文件。

Manifest

通過 manifest ,webpack 能夠?qū)?你的模塊映射到輸出 bundle 的過程 保持追蹤。

通俗點(diǎn)講,就是生成一個(gè) 源碼到輸出文件的映射

詳細(xì)請?jiān)L問 Manifest 管理輸出 | webpack

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • webpack使用學(xué)習(xí) 本分享學(xué)習(xí)借鑒webpack中文官網(wǎng),官網(wǎng)鏈接(中文文檔):https://www.web...
    腿毛怪丶叔叔閱讀 968評(píng)論 0 5
  • 1. 新建一個(gè)文件夾,命名為 webpack-cli , webpack-cli 就是你的項(xiàng)目名,項(xiàng)目名建議使用小...
    魯大師666閱讀 1,650評(píng)論 1 3
  • 記得2004年的時(shí)候,互聯(lián)網(wǎng)開發(fā)就是做網(wǎng)頁,那時(shí)也沒有前端和后端的區(qū)分,有時(shí)一個(gè)網(wǎng)站就是一些純靜態(tài)的html,通過...
    陽陽陽一堆陽閱讀 3,455評(píng)論 0 5
  • Webpack學(xué)習(xí)總結(jié) 此文只是自己學(xué)習(xí)webpack的一些總結(jié),方便自己查閱,閱讀不變,非常抱歉!! 下載安裝:...
    Lxs_597閱讀 1,087評(píng)論 0 0
  • 老爸不知從何時(shí)起喜歡上了喝酒,他對酒和煙的那種熱愛,勝過了許多東西,老媽對此痛心疾首,然而,每每喝醉言語都會(huì)出現(xiàn)失...
    黨睿閱讀 207評(píng)論 1 1

友情鏈接更多精彩內(nèi)容