webpack-實現loader、plugin

準備工做: npm init -y初始化一個項目 npm i webpack webpack-cli -D 建立一個webpack.config.js文件node

const path = require('path')

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist')
    },
    mode: 'development',
}
複製代碼

loader實現

經過實現一個簡單的字符串替換loader來了解下loader的工做原理webpack

// index.js
console.log('yuxiaoyu')

// 建立一個loader文件夾 先建立個replaceLoader.js
// loader就是一個函數,須要用聲明式函數,由於要取到上下文中的this,這個函數接受一個參數,是咱們要打包的源碼
module.exports = function(source) {
    console.log(source, this.query)
    return source.replace('yuxiaoyu', '於曉俞')
}

// 而後修改webpack.config.js
const path = require('path')

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist')
    },
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: path.resolve(__dirname, 'loader/replaceLoader.js'),
                    options: {
                        name: '實現loader'
                    }
                }
            }
        ]
    }
}
複製代碼

npx webpack以後,咱們能夠在main.js中看到index.js中的字符串已經被替換掉了 使用this.callback來返回多個結果信息,而不單單是源碼web

/* 
    this.callback()接受四個參數
    err,content,sourceMap,meta
 */
// 修改replaceLoader.js
module.exports = function(source) {
    console.log(source, this.query)
    // return source.replace('yuxiaoyu', '於曉俞')
    this.callback(null, source.replace('yuxiaoyu', '於曉俞'))
}
複製代碼

結果一樣能夠正常編譯npm

處理異步

官方提供this.async處理loader內的異步markdown

// 修改loader
module.exports = function(source) {
    console.log(source, this.query)
    // 咱們使用this.async來處理,他會返回this.callback
    // 定義一個異步處理,告訴webpack,這個loader裏有異步事件,在裏面調用下這個異步
    // callback 就是 this.callback 注意參數的使用
    const callback = this.async()
    setTimeout(() => {
        callback(null, source.replace('yuxiaoyu', '於曉俞'))
    }, 3000)
}
複製代碼

多個loader的使用

// 再建立一個同步的replaceLoaderSync.js
module.exports = function(source) {
    return source.replace('於曉俞', '程序猿')
}

//修改webpack.config.js文件
module: {
    rules: [
        {
            test: /\.js$/,
            use: [
                path.resolve(__dirname, 'loader/replaceLoaderSync.js'),
                {
                    loader: path.resolve(__dirname, 'loader/replaceLoader.js'),
                    options: {
                        name: '實現loader'
                    }
                }
            ]
        }
    ]
}
複製代碼

處理loader的路徑問題

咱們寫的配置文件地址寫法過於繁瑣,怎麼能像咱們npm i 下載的loader那樣,直接寫個loader名稱就好了呢?這就須要咱們再配置下webpack.config.jsapp

// 配置resolveLoader, 告訴webpack去哪裏查找loader,先去node_modules裏查找,找不到再去loader文件夾彙總
resolveLoader: {
    modules: ['node_modules', './loader']
},
module: {
    rules: [
        {
            test: /\.js$/,
            use: [
                // 改爲文件名
                'replaceLoaderSync',
                {
                    // 改爲文件名
                    loader: 'replaceLoader',
                    options: {
                        name: '實現loader'
                    }
                }
            ]
        }
    ]
}
複製代碼

一樣能夠編譯成功!
異步

plugins實現

plugin: 開始打包,在某個時刻,幫助咱們處理一些什麼事情的機制
一個插件由如下構成:
async

一個具名 JavaScript 函數。
在它的原型上定義 apply 方法。
指定一個觸及到 webpack 自己的 事件鉤子。
操做 webpack 內部的實例特定數據。
在實現功能後調用 webpack 提供的 callback。
咱們實現一個功能,在編譯完成後,在輸出文件時,同時輸出一個txt文本
函數

// 建立一個plugin文件夾 建立文件TxtWebpackPlugin.js
/* 
    插件是由一個構造函數(此構造函數上的 prototype 對象具備 apply 方法)的所實例化出來的。這個 apply 方法在安裝插件時,會被 webpack compiler 調用一次。apply 方法能夠接收一個 webpack compiler 對象的引用,從而能夠在回調函數中訪問到 compiler 對象。
 */
class TxtWebpackPlugin {
    constructor() {}
    apply(compiler) {
        // compiler.hooks中存放這各類鉤子,emit在編譯成功時輸出文件前執行的事件
        // 有些插件 hooks 是異步的。想要 tap(觸及) 某些 hooks,咱們可使用同步方式運行的 tap 方法,或者使用異步方式運行的 tapAsync 方法或 tapPromise 方法。
        compiler.hooks.emit.tapAsync('TxtWebpackPlugin', (compilation, callback) => {
            // 處理異步的事情
            let content = '生成的文件列表:\n'
            for (var filename in compilation.assets) {
                content += filename + '\n'
            }
            compilation.assets['filelist.txt'] = {
                source: function () {
                    return content
                },
                size: function () {
                    return content.length
                }
            }
            callback()
        });
    }
}
module.exports = TxtWebpackPlugin
複製代碼

相關文章
相關標籤/搜索