From ea005fe3ff0c3d9826b93f5132bf63fc27be8eac Mon Sep 17 00:00:00 2001 From: Chunpeng Huo Date: Mon, 10 Sep 2018 08:27:31 +1000 Subject: [PATCH] feat(bundler): support both 'json!f.json' and 'f.json' module id. Be nice to requirejs/system JSON plugin users. --- lib/build/bundle.js | 14 +++++++++++--- lib/build/bundled-source.js | 10 +++++++++- lib/build/bundler.js | 2 +- lib/build/loader-plugin.js | 19 +++++++------------ lib/build/utils.js | 11 +++++++++++ spec/lib/build/bundled-source.spec.js | 2 +- spec/mocks/bundler.js | 2 +- 7 files changed, 41 insertions(+), 19 deletions(-) diff --git a/lib/build/bundle.js b/lib/build/bundle.js index 5733b173d..ea1edea63 100644 --- a/lib/build/bundle.js +++ b/lib/build/bundle.js @@ -111,15 +111,23 @@ exports.Bundle = class { getBundledModuleIds() { let allModuleIds = this.getRawBundledModuleIds(); - return Array.from(allModuleIds).sort().map(id => { + let allIds = []; + Array.from(allModuleIds).sort().forEach(id => { let matchingPlugin = this.bundler.loaderOptions.plugins.find(p => p.matches(id)); if (matchingPlugin) { // make sure text! prefix is added, requirejs needs full form. // http://requirejs.org/docs/api.html#config-bundles - return matchingPlugin.createModuleId(id); + allIds.push(matchingPlugin.createModuleId(id)); + } else if (id.endsWith('.json')) { + allIds.push(id); + // be nice to requirejs json plugin users, add json! prefix + allIds.push(Utils.moduleIdWithPlugin(id, 'json', this.bundler.loaderOptions.type)); + } else { + allIds.push(id); } - return id; }); + + return allIds; } getBundledFiles() { diff --git a/lib/build/bundled-source.js b/lib/build/bundled-source.js index 8799eeeb1..0df41aead 100644 --- a/lib/build/bundled-source.js +++ b/lib/build/bundled-source.js @@ -4,6 +4,7 @@ const findDeps = require('./find-deps').findDeps; const cjsTransform = require('./amodro-trace/read/cjs'); const esTransform = require('./amodro-trace/read/es'); const allWriteTransforms = require('./amodro-trace/write/all'); +const {moduleIdWithPlugin} = require('./utils'); const logger = require('aurelia-logging').getLogger('BundledSource'); exports.BundledSource = class { @@ -49,6 +50,10 @@ exports.BundledSource = class { return this.bundler.loaderOptions.plugins; } + _getLoaderType() { + return this.bundler.loaderOptions.type; + } + _getLoaderConfig() { return this.bundler.loaderConfig; } @@ -95,6 +100,7 @@ exports.BundledSource = class { dependencyInclusion.description.browserReplacement(); let loaderPlugins = this._getLoaderPlugins(); + let loaderType = this._getLoaderType(); let loaderConfig = this._getLoaderConfig(); let moduleId = this.moduleId; let modulePath = this.path; @@ -115,7 +121,9 @@ exports.BundledSource = class { this.contents = matchingPlugin.transform(moduleId, modulePath, this.contents); } else if (path.extname(modulePath).toLowerCase() === '.json') { // support Node.js's json module - let contents = `define(\'${moduleId}\',[],function(){return JSON.parse(${JSON.stringify(this.contents)});});`; + let contents = `define(\'${moduleId}\',[],function(){return JSON.parse(${JSON.stringify(this.contents)});});\n`; + // be nice to requirejs json plugin users, add json! prefix + contents += `define(\'${moduleIdWithPlugin(moduleId, 'json', loaderType)}\',[\'${moduleId}\'],function(m){return m;});\n`; this.contents = contents; } else { // forceCjsWrap bypasses a r.js parse bug. diff --git a/lib/build/bundler.js b/lib/build/bundler.js index 8cf1e41c3..0ebec0567 100644 --- a/lib/build/bundler.js +++ b/lib/build/bundler.js @@ -43,7 +43,7 @@ exports.Bundler = class { Object.assign(this.loaderConfig, this.project.build.loader.config); this.loaderOptions.plugins = (this.loaderOptions.plugins || []).map(x => { - let plugin = new LoaderPlugin(this, x); + let plugin = new LoaderPlugin(this.loaderOptions.type, x); if (plugin.stub && this.loaderConfig.stubModules.indexOf(plugin.name) === -1) { this.loaderConfig.stubModules.push(plugin.name); diff --git a/lib/build/loader-plugin.js b/lib/build/loader-plugin.js index 7d8d7cfa2..427b1f2a3 100644 --- a/lib/build/loader-plugin.js +++ b/lib/build/loader-plugin.js @@ -1,8 +1,9 @@ 'use strict'; +const {moduleIdWithPlugin} = require('./utils'); exports.LoaderPlugin = class { - constructor(bundler, config) { - this.bundler = bundler; + constructor(type, config) { + this.type = type; this.config = config; this.name = config.name; this.stub = config.stub; @@ -19,19 +20,13 @@ exports.LoaderPlugin = class { } createModuleId(moduleId) { - let loderConfigType = this.bundler.loaderOptions.type; - - switch (loderConfigType) { - case 'require': - return 'text!' + moduleId; - case 'system': - return moduleId + '!text'; - default: - throw new Error(`Loader configuration style ${loderConfigType} is not supported.`); - } + // for backward compatibility, use 'text' as plugin name, + // to not break existing app with additional json plugin in aurelia.json + return moduleIdWithPlugin(moduleId, 'text', this.type); } }; function regExpFromExtensions(extensions) { return new RegExp('^.*(' + extensions.map(x => '\\' + x).join('|') + ')$'); } + diff --git a/lib/build/utils.js b/lib/build/utils.js index 916d702ab..64c96f7f0 100644 --- a/lib/build/utils.js +++ b/lib/build/utils.js @@ -27,6 +27,17 @@ exports.resolvePackagePath = function(packageName) { throw new Error(`cannot resolve npm package folder for "${packageName}"`); }; +exports.moduleIdWithPlugin = function(moduleId, pluginName, type) { + switch (type) { + case 'require': + return pluginName + '!' + moduleId; + case 'system': + return moduleId + '!' + pluginName; + default: + throw new Error(`Loader configuration style ${type} is not supported.`); + } +}; + exports.generateBundleName = function(contents, fileName, rev) { let hash; if (rev === true) { diff --git a/spec/lib/build/bundled-source.spec.js b/spec/lib/build/bundled-source.spec.js index 46f6a0fb2..efa917205 100644 --- a/spec/lib/build/bundled-source.spec.js +++ b/spec/lib/build/bundled-source.spec.js @@ -365,7 +365,7 @@ export {t}; expect(deps).toBeUndefined(); expect(bs.requiresTransform).toBe(false); expect(bs.contents) - .toBe('define(\'foo/bar/lo.json\',[],function(){return JSON.parse("{\\\"a\\\":1}");});'); + .toBe('define(\'foo/bar/lo.json\',[],function(){return JSON.parse("{\\\"a\\\":1}");});\ndefine(\'json!foo/bar/lo.json\',[\'foo/bar/lo.json\'],function(m){return m;});\n'); }); it('transforms npm package non-js file', () => { diff --git a/spec/mocks/bundler.js b/spec/mocks/bundler.js index 9dde5be44..7b7f572a6 100644 --- a/spec/mocks/bundler.js +++ b/spec/mocks/bundler.js @@ -20,7 +20,7 @@ module.exports = class Bundler { this.project = new ProjectMock(); this.loaderOptions = { type: 'require', - plugins: [new LoaderPlugin(this, { + plugins: [new LoaderPlugin('require', { name: 'text', extensions: ['.html', '.css'] })]