loader對比plugin
- loader:用於資源加載並處理各種語言的轉換/編譯(例如將不同語言轉換為javascript);
- plugin:用於資源加載以外的其他打包/壓縮/文件處理等功能;
loader原理,loader的自定義實現
loader 用途
loader 用於資源加載並處理各種語言的轉換/編譯(例如將不同語言轉換為javascript);
loader 實現原理,自定義實現
- loader 函數:loader 必須導出一個函數;它對資源文件進行處理後輸出內容;它類似於管道,可以串聯多個 loader,將返回值交給下一個 loader 繼續處理;
- loader 輸入:function 接收一個參數作為輸入,該參數的內容為文件內容
- loader 輸出:return 一個返回值作為輸出,該返回值為模塊導出的字符串;loader 需要將返回值作為一個模塊導出,才能更好的在webpack打包文件中使用,有三種導出方式;
- (1)按照 ES Modules 方式導出
- (2)按照 CommonJS 方式導出
- (3)loader 處理類似於管道,可以串聯多個 loader,可以直接將返回值交給下一個 loader 繼續處理;
// 自定義loader:
// 功能:導入markdown文件,將markdown轉換成html導出
// 插件:marked實現將markdown內容轉換成html的功能
const marked = require('marked')
// loader需要返回一段js代碼:因為在webpack加載時會將這段代碼拼接到打包代碼中~
// 輸入:function的參數作為輸入值:這裏是原有的markdown內容,source
// 輸出:return一個返回值作為輸出:這裏是轉換成html的內容,html(
// 輸出注意:1、需要將返回值作為一個模塊導出,才能更好的在webpack打包文件中使用
// 輸出注意:2、
module.exports = source => {
const html = marked(source)
// webpack將loader加載後會將代碼放到打包文件boundle.js中,一個loader對應一個(function(){}) 模塊;所以在loader中需要導出
// webpack的打包文件boundle.js中,支持CommonJS的方式、ES Modules的方式導出
// loader的
// 1、CommonJS的方式:輸出的模塊轉換為字符串的形式return
// return `module.exports = ${JSON.stringify(html)}`//JSON.stringify轉換html的換行符和空格
// 2、ES Modules:webpack內部會自動轉換export default導出的代碼
// return `export default ${JSON.stringify(html)}`
// 3、直接返回html,再將結果交給html-loader處理(loader是管道的形式處理,可以串聯)
return html
}
- 使用自定義loader
module: {
rules: [
{// 自定義loader,markdown-loader
test: /.md$/,
use: [ // 串聯多個loader,執行順序從下到上
'html-loader', // 安裝html-loader:npm install html-loader --save-dev
'./markdown-loader.js' // 自定義實現的loader
]
},
]
},
plugin原理,plugin的自定義實現
plugin 用途
用於資源加載以外的其他打包/壓縮/文件處理等功能;
plugin 插件機制(Hook 鈎子機制)
- 需要了解 taple 鈎子:https://gitee.com/ymcdhr/e-de...
- webpack 鈎子:https://webpack.docschina.org...
plugin 實現原理,自定義實現:
- plugin 是根據webpack生命週期的鈎子機制進行開發的,plugin通過在鈎子中掛載函數實現擴展;webpack鈎子參考文檔:https://webpack.docschina.org...
- plugin 必須是一個函數,或者包含apply方法的對象
- apply 方法有一個參數 compiler;
- 通過 compiler 可以給 webpack 編譯打包過程中添加鈎子;
- 通過鈎子的回調函數 callback 拿到打包結果對象 compilation(通過compilation.assets 獲取資源文件信息);
- 然後對打包結果對象 compilation 進行修改;
// 自定義plugin:
// 功能:將js文件中的註釋刪除調
// 自定義插件
// 自定義插件必須是一個函數,或者包含apply方法的對象
// plugin根據webpack生命週期鈎子函數開發的:https://webpack.docschina.org/api/compiler-hooks/#hooks
// compiler.hooks可以訪問鈎子
// 功能:清除打包過程中的註釋
class MyPlugin {
apply (compiler){
console.log('MyPlugin 啓動')
// emit鈎子的執行時機是:輸出打包好的資源文件 asset 到 output 目錄之前執行。
compiler.hooks.emit.tap('MyPlugin', compilation => {
// compilation => 可以理解為此次打包的結果
// compilation.assets => 獲取dist目錄的所有生成的資源文件信息,例如:bundle.js
for (const name in compilation.assets) {
// console.log(name)
// 獲取到資源的內容,例如:bundle.js裏面的內容
console.log(compilation.assets[name].source())
// 判斷文件是否為js文件
if (name.endsWith('.js')) {
// 替換掉js文件中的註釋
const contents = compilation.assets[name].source()
const withoutComments = contents.replace(/\/\*\*+\*\//g, '')
// 覆蓋原有內容
compilation.assets[name] = {
source: () => withoutComments, // 新的內容
size: () => withoutComments.length // 內容的大小,webpack必須的方法
}
}
}
})
}
}
module.exports = MyPlugin
- 在 webpack.config.js 配置中引入插件
const MyPlugin = require('./comment-plugin.js')
module.exports = {
// ...
plugins: [
new MyPlugin() // 自定義插件
]
}
特別鳴謝:拉勾教育前端高薪訓練營