用于 SystemJS 样式导入的自定义 Webpack 解析器!带装载机
Custom Webpack resolver for SystemJS style imports ! with-loader
我有一个项目正在使用 SystemJS - 这无法更改。我们还使用 StoryBooks,它使用 WebPack——这也无法改变。到目前为止,两人相处得非常融洽。但是,我有一个模块可以将文件作为纯文本加载并解析它们:
import stuff from './some-module!systemjs-plugin-text';
parseStuff(stuff);
如果我的项目使用的是 WebPack,上面的代码将如下所示:
import stuff from 'raw-loader!./some-module';
parseStuff(stuff);
由于 SystemJS 是 "primary" 模块加载器,我希望所有应用程序代码都以 SystemJS 为中心。我想为 webpack 编写一个自定义解析器来获取 SystemJS 样式的导入和 "flip" 它们(可以这么说)。代码如下所示:
const moduleMap = {
'systemjs-plugin-text': 'raw-loader'
};
const formatModuleIdForWebPack (systemjsId) {
const webpackId = systemjsId.split('!').reverse();
webpackId[0] = moduleMap[ webpackId[0] ] || webpackId[0];
return webpackId.join('!');
}
formatModuleIdForWebPack('./some-module!systemjs-plugin-text');
//-> 'raw-loader!./some-module'
我遵循了几个创建自定义解析器的示例 ( and here),但是 none 的有效负载包含了我重建请求对象所需的所有数据。有没有一种方法可以让我在模块解析的早期就连接到 WebPack 以实现我的目标?
我能够使用自定义加载程序来实现我的目标。这并不理想,但解析逻辑相当简单并且可以随着时间的推移变得更强大。使用此策略允许我仅将其应用于项目文件(node_modules
中 而非 的任何内容)。
{
test: /\.js$/,
loader: path.resolve('systemjs-loader.js'),
exclude: [
path.resolve('node_modules')
],
options: {
loaderMap: {
'systemjs-plugin-text': 'raw-loader'
}
}
}
...和加载程序代码:
const { getOptions } = require('loader-utils');
const escapeRegexp = require('escape-string-regexp');
/**
* Replaces systemjs-style loader syntax with webpack-style:
*
* ./some-module!systemjs-plugin -> webpack-plugin!./some-module
*/
module.exports = function (source) {
const options = getOptions(this);
const map = options.loaderMap;
if (!map) {
throw new Error('There is no need to use the systemjs loader without providing a `loaderMap`');
}
Object.keys(map).forEach(loader => {
// indexOf should be faster than regex.test
if (source.indexOf(loader) !== -1) {
const exp = new RegExp(`(['"])([^!]+)!${escapeRegexp(loader)}['"]`, 'g');
source = source.replace(exp, `${map[loader]}!`);
}
});
return source;
};
我有一个项目正在使用 SystemJS - 这无法更改。我们还使用 StoryBooks,它使用 WebPack——这也无法改变。到目前为止,两人相处得非常融洽。但是,我有一个模块可以将文件作为纯文本加载并解析它们:
import stuff from './some-module!systemjs-plugin-text';
parseStuff(stuff);
如果我的项目使用的是 WebPack,上面的代码将如下所示:
import stuff from 'raw-loader!./some-module';
parseStuff(stuff);
由于 SystemJS 是 "primary" 模块加载器,我希望所有应用程序代码都以 SystemJS 为中心。我想为 webpack 编写一个自定义解析器来获取 SystemJS 样式的导入和 "flip" 它们(可以这么说)。代码如下所示:
const moduleMap = {
'systemjs-plugin-text': 'raw-loader'
};
const formatModuleIdForWebPack (systemjsId) {
const webpackId = systemjsId.split('!').reverse();
webpackId[0] = moduleMap[ webpackId[0] ] || webpackId[0];
return webpackId.join('!');
}
formatModuleIdForWebPack('./some-module!systemjs-plugin-text');
//-> 'raw-loader!./some-module'
我遵循了几个创建自定义解析器的示例 (
我能够使用自定义加载程序来实现我的目标。这并不理想,但解析逻辑相当简单并且可以随着时间的推移变得更强大。使用此策略允许我仅将其应用于项目文件(node_modules
中 而非 的任何内容)。
{
test: /\.js$/,
loader: path.resolve('systemjs-loader.js'),
exclude: [
path.resolve('node_modules')
],
options: {
loaderMap: {
'systemjs-plugin-text': 'raw-loader'
}
}
}
...和加载程序代码:
const { getOptions } = require('loader-utils');
const escapeRegexp = require('escape-string-regexp');
/**
* Replaces systemjs-style loader syntax with webpack-style:
*
* ./some-module!systemjs-plugin -> webpack-plugin!./some-module
*/
module.exports = function (source) {
const options = getOptions(this);
const map = options.loaderMap;
if (!map) {
throw new Error('There is no need to use the systemjs loader without providing a `loaderMap`');
}
Object.keys(map).forEach(loader => {
// indexOf should be faster than regex.test
if (source.indexOf(loader) !== -1) {
const exp = new RegExp(`(['"])([^!]+)!${escapeRegexp(loader)}['"]`, 'g');
source = source.replace(exp, `${map[loader]}!`);
}
});
return source;
};