LoginSignup
13
6

More than 5 years have passed since last update.

[ 雑に対策 ] Webpackプラグインでエラーが出たので、作り方を調べて直してみた。

Last updated at Posted at 2019-01-29

DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks instead


こんなエラーが出て困ってる人のヒントになれば幸い。

結果

↓こうしたら動きました。

index.js
const fs = require('fs');
const RawSource = require('webpack-sources').RawSource;
const SourceMapSource = require('webpack-sources').SourceMapSource;
const iconv = require('iconv-lite');
let ModuleFilenameHelpers = require('webpack').ModuleFilenameHelpers;
if (!ModuleFilenameHelpers) {
  ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers')
}

class EncodingPlugin {
  constructor(options) {
    if (typeof options === 'string') {
      this.options = {
        encoding: options
      }
    } else {
      this.options = options || {}
    }
  }

  apply(compiler) {
    let options = this.options;
    options.test = options.test || /(\.js|\.css)($|\?)/i;

    let matchFileName = ModuleFilenameHelpers.matchObject.bind(undefined, options);

    compiler.hooks.emit.tapPromise('EncodingPlugin', compilation => {
      return new Promise((resolve, reject) => {
        let files = Object.keys(compilation.assets).filter(matchFileName);
        files.forEach(function (file) {
          let asset = compilation.assets[file];
          try {
            let source, map;
            if (asset.sourceAndMap) {
              let sourceAndMap = asset.sourceAndMap();
              source = sourceAndMap.source;
              map = sourceAndMap.map
            } else {
              source = asset.source();
              map = typeof asset.map === 'function'
                ? asset.map()
                : null
            }

            let encodedSource = iconv.encode(source, options.encoding, options.config);
            if (asset.existsAt && fs.existsSync(asset.existsAt)) {
              fs.writeFileSync(asset.existsAt, encodedSource)
            }

            compilation.assets[file] = map
              ? new SourceMapSource(encodedSource, file, map)
              : new RawSource(encodedSource)

          } catch (e) {
            compilation.errors.push(new Error(file + ' from EncodingPlugin: ' + e.message))
          }
        });

        console.log('Assets converted to ' + options.encoding);
        resolve();
      });
    });
  }
}

module.exports = EncodingPlugin;

経緯

今開発しているサイトの文字コードが EUC-JP 限定だったので、
JavaScriptの文字コードを EUC-JP にしたく、
webpack-encode-plugin というプラグインを実装してみたところ、
↓こんなエラーが出て怒られた。

DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks instead

webpack-encode-plugin
https://www.npmjs.com/package/webpack-encode-plugin

ググってみたけどこのプラグインのissuが見つからず。。

DeprecationWarning: Tapable.plugin is deprecated. Use new API on .hooks instead

でググってみたけど解決策が見つからなかった。

よし、とりあえず直訳だ!

英語も得意じゃないので、とりあえず Google翻訳 にかけてみた。
結果が↓こちら

DeprecationWarning:Tapable.pluginは非推奨です。代わりに.hooksに新しいAPIを使用してください

ふむ。
まあ要は Plugin 内の記述方法を新しいAPIに変えろと言っているっぽい。

Tapable.plugin とはなんぞや?

「非推奨です。」って言われている Tapable.plugin がなんのか分からなかったので、
「site:webpack.js.org Tapable.plugin」でググってみたら、
Plugin API のページがヒットした。

Plugin API
https://webpack.js.org/api/plugins/

そこに Tapable class という記述を発見。
Tapable | Plugin API
https://webpack.js.org/api/plugins/#tapable

ドキュメントへのリンクも発見。
webpack/tapable | GitHub
https://github.com/webpack/tapable

「この辺を読み解いて、ソースコードいじればなんとかなるかも?」 と思った。

ひとまずプラグインの中身を見てみた

GitHub に上がっていたソースコードが↓こちら
https://github.com/ricosmall/webpack-encode-plugin/blob/master/index.js

う〜ん、どの辺が Tapable クラスか分からず。。。

Tapable.plugin webpack でもググってみた

↓こんなページを発見
Extending with Plugins
https://survivejs.com/webpack/extending/plugins/

webpackプラグインの書き方ページっぽいけど、
今回エラーの出た webpack-encode-plugin の記述方法がこれによく似てた。
この書き方がもう古いってことなんだろうな。。。と推測。

Plugin API のページを再度確認

Plugin Types の箇所に

compiler.hooks...

という記述を発見。

以前は、 compiler.plugin としていた書き方が、
compiler.hooks というメソッドに変わったんだなと推測。

Plugin Types
https://webpack.js.org/api/plugins/#plugin-types

さて、

compiler.hooks. のあとはどうする?

Compiler Hooks というページがあったので、
見てみたがいっぱいあった。。。

でもなんとなく、 emit を選択。

文字コード変換は output ディレクトリへの出力直前がよい気がしたので。

compiler.hooks.emit. のあとはどうする?

Hook types に色々あった。
https://github.com/webpack/tapable#hook-types

非同期の Promise ベースで resolve() 返せれば無難かなと思い、
.tapPromise() を選択

組み直した結果うまく機能して文字コード変換されました。

だいぶ大雑把な修正のしかたをしたけど、
まあ動いたのでよし。

時間に余裕ができたらもっとちゃんと調べて理解してみよう。

なんとかなったけども

記述に問題があったりする可能性大だと思っているので、
大元の webpack-encode-plugin へはこの内容は送ってません。

おかしな点などありましたらご指摘いただけると嬉しいです(>人<)

13
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
6