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"
}