🙄

〜loader選びに明け暮れて〜Webpack5でejsを使いたかった話

2021/03/10に公開

背景

当方フロントエンドもWebpackも初心者ですが、どうしてもWebpack5でejsを使いたくてloaderを探し回りました。
テンプレートエンジンはejs以外使ったことがないという安易な理由でとりあえずejsを選定。
今まではgulpで動かしていましたが、脱gulpを目指しWebpack5で構築します。

Webpackでejsのloaderが必要な理由

調べきれていないですが、WebpackHTMLPluginの利用でejsファイルの利用自体はできるものの、肝心のincludeがloaderなしではできなさそうでした。

試したloader

  • ejs-plain-loader 1.4.1 (最終的にこれが動いたので採用)
  • ejs-compiled-loader 3.0.0
  • ejs-html-loader 4.0.1

ejs-plain-loader [cf.]

  • 最初ドキュメントの通りに下記のようにwebpack.config.jsを記載し実行するも、エラーに遭遇。
    webpack.config.js
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
        // ...
        module: {
    	rules: [{
    	    test: /\.ejs$/i,
    	    use: [{
    		loader: 'html-loader', // loader for html files goes here
    		options: {
    		    attrs: [':src', ':data-src', 'source:srcset', 'source:data-srcset'], // load(require) images, videos or other resources
    		    interpolate: true
    		}
    	    }, {
    		loader: 'ejs-plain-loader'
    	    }]
    	}]
        },
        plugins: [
    	new HtmlWebpackPlugin({ // plugin for templates goes here
    	    template: './src/views/index.ejs'
    	})
        ]
        // ...
    }
    
    // エラー内容
    ERROR in   Error: Child compilation failed:
    Module build failed (from ./node_modules/html-loader/dist/cjs.js):
    ValidationError: Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
    - options has an unknown property 'interpolate'. These properties are valid:
     object { preprocessor?, sources?, minimize?, esModule? }
    

見ると、 interpolateってなんぞや?html-loaderではpreprocessorかsourcesかminimizeかesModuleかしかoptionsは定義してないよ! みたいなことが書いてある。のだと思う。たぶん。

ということで、optionsを一度きれいさっぱりにして見たら動きました。optionsを追加することになったらまた追記します。

webpack.config.js
      {
	test: /\.ejs$/,
	use: [
	  "html-loader", 
	  "ejs-plain-loader"
	],
      },

実行結果

npm run build を実行した結果、無事includeしたファイルもコンパイルされました。

./src/index.ejs
<h2>message</h2>
<%- include('./pages/index.ejs') %>
./src/pages/index.ejs
<p>hello</p>
./dist/index.html
<h2>message</h2>
<p>hello</p>

不採用: ejs-compiled-loader [cf.]

  • 下記エラーに遭遇。
A valid query string passed to parseQuery should begin with '?'

調べると、某issueで最後の方に「Webpack5ではこのloaderは捨ててWebpack上で全て行うようにしたよ〜今までありがとう」的なことが書かれているようです。ということでこちらは断念。

不採用: ejs-html-loader [cf.]

  • 下記エラーに遭遇し断念。ドキュメントにあった必要なloaderはインストールしたはずなのに…。
ERROR in   Error: Child compilation failed:
  Module parse failed: Unexpected token (1:0)
  File was processed with these loaders:
   * ./node_modules/html-webpack-plugin/lib/loader.js
   * ./node_modules/ejs-html-loader/lib/index.js
  You may need an additional loader to handle the result of these loaders.
  > <!DOCTYPE html>
  | <html lang="ja">
  | <head>
  ModuleParseError: Module parse failed: Unexpected token (1:0)
  File was processed with these loaders:
   * ./node_modules/html-webpack-plugin/lib/loader.js
   * ./node_modules/ejs-html-loader/lib/index.js
  You may need an additional loader to handle the result of these loaders.
  > <!DOCTYPE html>
  | <html lang="ja">
  | <head>

Discussion