webpack4學習筆記(四)

前言

這是我花了幾個星期學習webpack4的學習筆記。內容不夠細,由於一些相對比較簡單的,就隨意帶過了。但願文章能給你們帶來幫助。若有錯誤,但願及時指出。例子都在learn-webpack倉庫上。若是你從中有所收穫的話,但願你能給個人github點個starjavascript

編寫loader

// index.js
console.log('hello, atie')

配置webpack.config.jshtml

// webpack.config.js

module: {
  rules: [
    {
      test: /\.js$/,
      include: /src/,
      loader: path.resolve(__dirname, './loaders/replaceLoader.js')
    }
  ]
},
// 函數不能使用箭頭函數
module.exports = function(source) {
    console.log(source, 'source')
    return source.replace('atie', 'world')
}

loader文件其實就是導出一個函數,source就是webpack打包出的js字符串。這裏的loader就是將上面的console.log('hello, atie')替換爲console.log('hello, world')java

打包下代碼,不出所料。控制檯就會打印出hello, worldwebpack

當你想要給loader傳參時,可配置以下git

module: {
  rules: [
    {
      test: /\.js$/,
      include: /src/,
      use: [{
        loader: path.resolve(__dirname, './loaders/replaceLoader.js'),
        options: {
          name: 'haha'
        }
      }]
    }
  ]
},

經過給loader添加optionsgithub

這樣loader中就能夠經過this.query獲取該參數了web

module.exports = function(source) {
      // 控制檯輸出:console.log('hello atie') { name: 'haha' } source
    console.log(source, this.query, 'source')
    return source.replace('atie', 'world')
}

固然變量不必定非要經過this.query來獲取npm

可經過loader-utils這個包來獲取傳入的變量app

安裝: npm i loader-utils -D異步

const loaderUtils = require('loader-utils')

// 函數不能使用箭頭函數
module.exports = function(source) {
    // console.log(source, this.query, 'source')
    const options = loaderUtils.getOptions(this)
    console.log(options, 'options') // { name: 'haha' } 'options'
    return source.replace('atie', 'world')
}

打印出來的與上面this.query一致

上面都是直接經過return返回的,那麼咱們還有沒有其餘方法返回loader翻譯後的代碼呢?`

這裏就會用到callback

this.callback(
  err: Error | null,
  content: string | Buffer,
  sourceMap?: SourceMap,
  meta?: any
);

上面的代碼就能夠改寫成

module.exports = function(source) {
    const options = loaderUtils.getOptions(this)
    const result = source.replace('atie', options.name)
    this.callback(null, result)
}

callback優點在於它能夠傳遞多餘的參數

module.exports = function(source) {
    setTimeout(() => {
        return source.replace('atie', 'world')
    }, 1000)
}

當咱們把return包到異步方法裏,打包的時候就會報錯,那麼咱們該怎麼辦呢?

這個時候就須要用到this.async()

module.exports = function(source) {
    const callback = this.async()
    setTimeout(() => {
        callback(null, source.replace('atie', 'world'))
    }, 2000)
}

經過調用this.async()返回的callback方法來返回結果

use中的loader執行順序,先右後左,先下後上

編寫plugin

在根目錄下新建plugins文件夾,並新建copyright-webpack-plugin.js,內容以下:

class Copyright {
    constructor() {
        console.log('this is plugin')
    }
    apply(compiler) {
    }
}
module.exports = Copyright

注意:apply這個方法必須存在,否則插件被執行的時候會報錯。

配置webpack.config.js,以下:

const Copyrgiht = require('./plugins/copyright-webpack-plugin.js')

...

plugins: [
  new Copyrgiht()
]

執行下打包命令後

this is plugin
Hash: 479baeba2207182096f8
Version: webpack 4.30.0
Time: 615ms
Built at: 2019-05-08 23:05:08
     Asset       Size  Chunks             Chunk Names
 bundle.js   3.77 KiB    main  [emitted]  main
index.html  182 bytes          [emitted]

控制檯打印出了this is plugin

接下來,咱們繼續探索插件的奧祕

在使用插件的時候還能夠傳參

// webpack.config.js
plugins: [
  new Copyrgiht({
    name: 'atie'
  })
]
class Copyright {
    constructor(options) {
        // console.log(options, 'this is plugin')
          this.options = options
    }
    apply(compiler) {
          console.log(this.options)
    }
}

執行下打包命令:

{ name: 'atie' }
Hash: 479baeba2207182096f8
Version: webpack 4.30.0
Time: 742ms
Built at: 2019-05-08 23:24:10
     Asset       Size  Chunks             Chunk Names
 bundle.js   3.77 KiB    main  [emitted]  main
index.html  182 bytes          [emitted]

控制就會輸出 {name: 'atie'}

webpack在調用apply會傳遞一個compiler參數,這個參數能夠作不少事情,具體能夠參考webpack官網

這裏介紹下鉤子

class Copyright {
    apply(compiler) {
        compiler.hooks.emit.tapAsync('Copyright', (compilation,callback) => {
            console.log(compilation.assets, '以具備延遲的異步方式觸及 run 鉤子。');
            compilation.assets['copyright.txt'] = {
                source: function() {
                    return 'copyright by atie'
                },
                size: function() {
                    return 17
                }
            }
            callback()
        })
    }
}

module.exports = Copyright

該鉤子是在文件生成前觸發的。咱們在文件生成前,在asset對象上在加一個文件對象

打包以後

.
├── bundle.js
├── copyright.txt
└── index.html

能夠看到多了一個copyright.txt,也就是咱們上面建立的文件。點開該文件還會看到裏面的內容正是copyright by atie

相關文章
相關標籤/搜索