Webpack "require" in loader that runs up the stack again

359 Views Asked by At

I've written a simple loader that uses EJS to load templates for JSON and XML files. I'd like to be able to use require to get image paths like what happens when the webpack loader is used, but instead it tries to load the file directly as JavaScript. I get this error:

ERROR in ./favicons/manifest.json.ejs
    Module build failed: {root}/favicons/android-chrome-192x192.png:1
    (function (exports, require, module, __filename, __dirname) { �PNG
                                                                  ^
    SyntaxError: Invalid or unexpected token
        at Object.exports.runInThisContext (vm.js:78:16)
        at Module._compile (module.js:543:28)
        at Object.Module._extensions..js (module.js:580:10)
        at Module.load (module.js:488:32)
        at tryModuleLoad (module.js:447:12)
        at Function.Module._load (module.js:439:3)
        at Module.require (module.js:498:17)
        at require (internal/module.js:20:19)
        at Object.require ({root}/loaders/simple-ejs.js:11:14)
        at eval (eval at compile ({root}/node_modules/ejs/lib/ejs.js:481:12), <anonymous>:11:24)
        at returnedFn ({root}/node_modules/ejs/lib/ejs.js:512:17)
        at Object.exports.render ({root}/ejs/lib/ejs.js:316:37)
        at Object.module.exports ({root}/loaders/simple-ejs.js:8:14)
     @ ./~/html-webpack-plugin/lib/loader.js!./index.html.ejs 12:10-49

loaders/simple-ejs.js:

let ejs = require('ejs');
let resolve = require('resolve-path');

module.exports = function(source) {
  this.cacheable();
  var self = this;
  return ejs.render(source, {
    require: function(path) {
      let absolutePath = path.match(/^\./) ? resolve(self._module.context, path) : path ;
      require(absolutePath);
    }
  });
};

webpack.config.js:

let path = require("path");
let ExtractTextPlugin = require("extract-text-webpack-plugin");
let CompressionPlugin = require("compression-webpack-plugin");
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    main: ["./src/main.jsx"]
  },

  output: {
    path: path.resolve(__dirname, "./dist"),
    publicPath: "/",
    filename: "[name]_[hash].js"
  },

  plugins: [
    new ExtractTextPlugin("styles_[contenthash].css"),
    new CompressionPlugin({ test: /\.(js|css)$/ }),
    new HtmlWebpackPlugin({ inject: false, template: 'index.html.ejs' })
  ],

  module: {
    loaders: [
      {
        test: /\.(jpeg|png|woff|ttf|svg|eot|jpg)$/,
        loader: 'file-loader'
      },
      {
        test: /\.(s)?css$/,
        loader: ExtractTextPlugin.extract({
          fallbackLoader: "style-loader",
          loader: "css-loader!sass-loader?sourceMap"
        })
      },
      {
        test: /\.js(x)?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          cacheDirectory: true,
        }
      },
      {
        test: /favicons\/.*$/,
        loader: 'file-loader'
      },
      {
        test: /favicons\/.*\.(json|xml)\.ejs$/,
        loader: 'file-loader?filename=[name]!./loaders/simple-ejs'
      }
    ]
  }
};

index.html.ejs:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <link href="<%= htmlWebpackPlugin.files.css %>" rel="stylesheet">

  <link rel="apple-touch-icon" sizes="180x180" href="<%= require('./favicons/apple-touch-icon.png') %>">
  <link rel="icon" type="image/png" href="<%= require('./favicons/favicon-32x32.png') %>" sizes="32x32">
  <link rel="icon" type="image/png" href="<%= require('./favicons/favicon-16x16.png') %>" sizes="16x16">
  <link rel="manifest" href="<%= require('./favicons/manifest.json.ejs') %>">
  <link rel="mask-icon" href="<%= require('./favicons/safari-pinned-tab.svg') %>" color="#5bbad5">
  <meta name="apple-mobile-web-app-title" content="Test App">
  <meta name="application-name" content="Test App">
  <meta name="theme-color" content="#ffffff">

  <meta name=viewport content="width=device-width, initial-scale=1">
</head>
<body>
  <div id="app" class="loading">
  </div>

  <script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
</body>
</html>

favicons/manifjest.json.ejs:

{
  "name": "Test App",
  "icons": [
    {
      "src": "<%= require('./android-chrome-192x192.png') %>",
      "sizes": "192x192",
      "type": "image\/png"
    },
    {
      "src": "<%= require('./android-chrome-512x512.png') %>",
      "sizes": "512x512",
      "type": "image\/png"
    }
  ],
  "theme_color": "#ffffff",
  "display": "standalone"
}
0

There are 0 best solutions below