<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                在這一小節我們會來介紹如何創建一個 webpack 可用的 loader。 ## loader 是一個函數 先來看一個簡單的例子: ``` "use strict"; const marked = require("marked"); const loaderUtils = require("loader-utils"); module.exports = function (markdown) { // 使用 loaderUtils 來獲取 loader 的配置項 // this 是構建運行時的一些上下文信息 const options = loaderUtils.getOptions(this); this.cacheable(); // 把配置項直接傳遞給 marked marked.setOptions(options); // 使用 marked 處理 markdown 字符串,然后返回 return marked(markdown); }; ``` 這是 [markdown-loader](https://github.com/peerigon/markdown-loader) 的實現代碼,筆者添加了一些代碼說明,看上去很簡單。 markdown-loader 本身僅僅只是一個函數,接收模塊代碼的內容,然后返回代碼內容轉化后的結果。webpack loader 的本質就是這樣的一個函數。 上述代碼中用到的 [loader-utils](https://github.com/webpack/loader-utils) 是 webpack 官方提供的一個工具庫,提供 loader 處理時需要用到的一些工具方法,例如用來解析上下文 loader 配置項的 `getOptions`。關于這個工具庫的內容和功能不是特別復雜,就不展開了,直接參考這個庫的官方文檔即可。 代碼中還用到了 [marked](https://github.com/markedjs/marked),marked 是一個用于解析 Markdown 的類庫,可以把 Markdown 轉為 HTML,markdown-loader 的核心功能就是用它來實現的。基本上,webpack loader 都是基于一個實現核心功能的類庫來開發的,例如 [sass-loader](https://github.com/webpack-contrib/sass-loader) 是基于 [node-sass](https://github.com/sass/node-sass) 實現的,等等。 ## 開始一個 loader 的開發 我們可以在 webpack 配置中直接使用路徑來指定使用本地的 loader,或者在 loader 路徑解析中加入本地開發 loader 的目錄。看看配置例子: ``` // ... module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: path.resolve('./loader/index.js'), // 使用本地的 ./loader/index.js 作為 loader }, ], }, // 在 resolveLoader 中添加本地開發的 loaders 存放路徑 // 如果你同時需要開發多個 loader,那么這個方式會更加適合你 resolveLoader: { modules: [ 'node_modules', path.resolver(__dirname, 'loaders') ], }, ``` 如果你熟悉 Node 的話,也可以使用 `npm link` 的方式來開發和調試,關于這個方式,可以參考 npm 的官方文檔 [npm-link](https://docs.npmjs.com/cli/link)。 ## 復雜一點的情況 當我們選擇上述任意一種方法,并且做好相應的準備后,我們就可以開始寫 loader 的代碼了,然后通過執行 webpack 構建來查看 loader 是否正常工作。 上面已經提到,loader 是一個函數,接收代碼內容,然后返回處理結果,有一些 loader 的實現基本上就是這么簡單,但是有時候會遇見相對復雜一點的情況。 首先 loader 函數接受的參數是有三個的:`content, map, meta`。`content` 是模塊內容,但不僅限于字符串,也可以是 buffer,例如一些圖片或者字體等文件。`map` 則是 sourcemap 對象,`meta` 是其他的一些元數據。loader 函數單純返回一個值,這個值是當成 content 去處理,但如果你需要返回 sourcemap 對象或者 meta 數據,甚至是拋出一個 loader 異常給 webpack 時,你需要使用 `this.callback(err, content, map, meta)` 來傳遞這些數據。 我們日常使用 webpack,有時候會把多個 loader 串起來一起使用,最常見的莫過于 css-loader 和 style-loader 了。當我們配置 `use: ['bar-loader', 'foo-loader']` 時,loader 是以相反的順序執行的,即先跑 foo-loader,再跑 bar-loader。這一部分內容在配置 loader 的小節中有提及,這里再以開發 loader 的角度稍稍強調下,搬運官網的一段說明: * 最后的 loader 最早調用,傳入原始的資源內容(可能是代碼,也可能是二進制文件,用 buffer 處理) * 第一個 loader 最后調用,期望返回是 JS 代碼和 sourcemap 對象(可選) * 中間的 loader 執行時,傳入的是上一個 loader 執行的結果 雖然有多個 loader 時遵循這樣的執行順序,但對于大多數單個 loader 來說無須感知這一點,只負責好處理接受的內容就好。 還有一個場景是 loader 中的異步處理。有一些 loader 在執行過程中可能依賴于外部 I/O 的結果,導致它必須使用異步的方式來處理,這個使用需要在 loader 執行時使用 `this.async()` 來標識該 loader 是異步處理的,然后使用 `this.callback` 來返回 loader 處理結果。例子可以參考官方文檔:[異步 loader](https://doc.webpack-china.org/api/loaders/#%E5%BC%82%E6%AD%A5-loader)。 ## Pitching loader 我們可以使用 `pitch` 來跳過 loader 的處理,`pitch` 方法是 loader 額外實現的一個函數,看下官方文檔中的一個例子: ``` module.exports = function(content) { return someSyncOperation(content, this.data.value); // pitch 的緣故,這里的 data.value 為 42 } // 掛在 loader 函數上的 pitch 函數 module.exports.pitch = function(remainingRequest, precedingRequest, data) { data.value = 42; } ``` 我們可以簡單把 `pitch` 理解為 loader 的前置鉤子,它可以使用 `this.data` 來傳遞數據,然后具備跳過剩余 loader 的能力。 在一個 `use` 配置中所有 loader 執行前會先執行它們對應的 `pitch`,并且與 loader 執行順序是相反的,如: ``` use: [ 'bar-loader', 'foo-loader', ], // 執行 bar-loader 的 pitch // 執行 foo-loader 的 pitch // bar-loader // foo-loader ``` 其中,當 pitch 中返回了結果,那么執行順序會回過頭來,跳掉剩余的 loader,如 `bar-loader` 的 pitch 返回結果了,那么執行只剩下 ``` // 執行 bar-loader 的 pitch ``` 可能只有比較少的 loader 會用到 pitch 這個功能,但有的時候考慮實現 loader 功能需求時把 pitch 納入范圍會有不一樣的靈感,它可以讓你更加靈活地去定義 loader 的執行。 這里的簡單介紹僅做拋磚引玉之用,詳細的學習和了解可以參考官方文檔 [Pitching loader](https://doc.webpack-china.org/api/loaders/#%E8%B6%8A%E8%BF%87-loader-pitching-loader-) 或者 bundler-loader 源碼 [bundler-loader](https://github.com/webpack-contrib/bundle-loader/blob/master/index.js)。 ## loader 上下文 上述提及的一些代碼會使用到 `this`,即 loader 函數的上下文,包括 `this.callback` 和 `this.data` 等,可以這樣簡單地理解: `this` 是作為 loader 運行時數據和調用方法的補充載體。 loader 上下文有很多運行時的信息,如 `this.context` 和 `this.request` 等等,而最重要的方法莫過于 `this.callback` 和 `this.async`,關于上下文這里不做展開,官方文檔有比較詳細的說明:[loader API](https://doc.webpack-china.org/api/loaders/#this-version)。當你在開發 loader 過程中發現需要某些運行時數據時,就可以查閱 loader API,基本上該有的數據都有了。 ## 一個好 loader 是怎么樣的 loader 作為 webpack 解析資源的一種擴展方式,最重要的是足夠簡單易用,專注于處理自己那一塊的內容,便于維護,可以和其他多個 loader 協同來處理更加復雜的情況。 官方對于 loader 的使用和開發有一些準則,一個好的 loader 應該符合官方的這些定義:[Loader 準則](https://doc.webpack-china.org/contribute/writing-a-loader/#%E7%94%A8%E6%B3%95%E5%87%86%E5%88%99-guidelines-)。 社區中有相當多的優秀 loader 可以作為參考,例如剛開始提及的 markdown-loader,相當地簡單易用。由于 loader 的這種準則和特性,大部分的 loader 源碼都相對容易解讀,便于我們學習參考。 作為一個 loader 開發者,你應該盡可能遵循這些準則(有些特殊情況需要特殊處理),這樣會讓你開發出質量更高、更易維護和使用的 webpack loader。 ## 小結 本小節我們從下面幾個方面介紹了如何開發一個 webpack loader: * loader 本質上的實現是一個函數 * 如何開始著手開發一個 loader * loader 的輸入和輸出 * pitch 函數的作用 * loader 函數的上下文 * 一個好的 loader 是怎么樣的 loader 的實現相對簡單,webpack 社區現成可用的 loader 很多,當你在開發 loader 時遇見了問題,不妨去查閱一下現有 loader 的源碼,或許會有不一樣的靈感。 ## 例子 本小節提及的一些簡單的 Demo 可以在 [webpack-examples](https://github.com/teabyii/webpack-examples) 找到。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看