webpack: resolveLoader / alias with query / options
Sometimes you write a post for the ages. Sometimes you write one you hope is out of date before you hit "publish". This is one of those.
There's a bug in webpack's enhanced-resolve. It means that you cannot configure an aliased loader using the query
(or options
in the webpack 2 nomenclature). Let me illustrate; consider the following code:
module.exports = {
// ...
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader',
query: {
entryFileIsJs: true
}
}
]
}
}
module.exports.resolveLoader = { alias: { 'ts-loader': require('path').join(__dirname, "../../index.js")
At the time of writing, if you alias a loader as above, then the query
/ options
will *not* be passed along. This is bad, particularly given the requirement in webpack 2 that configuration is no longer possible through extending the webpack.config.js
. So what to do? Well, when this was a problem previously the marvellous James Brantly had a workaround. I've taken that and run with it:
var config = {
// ...
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader',
query: {
entryFileIsJs: true,
},
},
],
},
};
module.exports = config;
var loaderAliasPath = require('path').join(__dirname, '../../../index.js');
var rules = config.module.loaders || config.module.rules;
rules.forEach(function (rule) {
var options = rule.query || rule.options;
rule.loader = rule.loader.replace(
'ts-loader',
loaderAliasPath + (options ? '?' + JSON.stringify(options) : ''),
);
});
This approach stringifies the query
/ options
and suffixes it to the aliased path. This works as long as the options you're passing are JSON-able (yes it's a word).
As I said earlier; hopefully by the time you read this the workaround will no longer be necessary again. But just in case....