Skip to content

Commit

Permalink
feat(bundler): support npm package shipped in native es module
Browse files Browse the repository at this point in the history
Although Nodejs doesn't support es module by default, webpack supports it. Some npm packages like bpmn-js are shipped in native es module format. They are consumable by webpack but not Nodejs. This feature closes the gap between our built-in bundler and webpack.

closes #872
  • Loading branch information
3cp committed Sep 27, 2018
1 parent 8fa8800 commit 1669a6f
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 25 deletions.
39 changes: 15 additions & 24 deletions lib/build/amodro-trace/read/cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,23 @@ var parse = require('../lib/parse');
// https://github.com/requirejs/r.js/issues/980
module.exports = function cjs(fileName, fileContents, forceWrap) {
// Strip out comments.
try {
var preamble = '',
commonJsProps = parse.usesCommonJs(fileName, fileContents);
var preamble = '',
commonJsProps = parse.usesCommonJs(fileName, fileContents);

// First see if the module is not already RequireJS-formatted.
if (!forceWrap && (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps)) {
return fileContents;
}

if (commonJsProps && (commonJsProps.dirname || commonJsProps.filename)) {
preamble = 'var __filename = module.uri || \'\', ' +
'__dirname = ' +
'__filename.substring(0, __filename.lastIndexOf(\'/\') + 1); ';
}

// Construct the wrapper boilerplate.
fileContents = 'define(function (require, exports, module) {' +
preamble +
fileContents +
'\n});\n';

} catch (e) {
console.log('commonJs.convert: COULD NOT CONVERT: ' + fileName +
', so skipping it. Error was: ' + e);
// First see if the module is not already RequireJS-formatted.
if (!forceWrap && (parse.usesAmdOrRequireJs(fileName, fileContents) || !commonJsProps)) {
return fileContents;
}

return fileContents;
if (commonJsProps && (commonJsProps.dirname || commonJsProps.filename)) {
preamble = 'var __filename = module.uri || \'\', ' +
'__dirname = ' +
'__filename.substring(0, __filename.lastIndexOf(\'/\') + 1); ';
}

// Construct the wrapper boilerplate.
return 'define(function (require, exports, module) {' +
preamble +
fileContents +
'\n});\n';
};
10 changes: 10 additions & 0 deletions lib/build/amodro-trace/read/es.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';
const transform = require('babel-core').transform;

// use babel to translate native es module into AMD module
module.exports = function es(fileName, fileContents) {
return transform(fileContents, {
babelrc: false,
plugins: ['transform-es2015-modules-amd']
}).code;
};
17 changes: 16 additions & 1 deletion lib/build/bundled-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
const path = require('path');
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 logger = require('aurelia-logging').getLogger('BundledSource');

Expand Down Expand Up @@ -117,7 +118,21 @@ exports.BundledSource = class {
// forceCjsWrap bypasses a r.js parse bug.
// See lib/amodro-trace/read/cjs.js for more info.
let forceCjsWrap = !!modulePath.match(/\/(cjs|commonjs)\//i);
let contents = cjsTransform(modulePath, this.contents, forceCjsWrap);
let contents;

try {
contents = cjsTransform(modulePath, this.contents, forceCjsWrap);
} catch (ignore) {
// file is not in amd/cjs format, try native es module
try {
contents = esTransform(modulePath, this.contents);
} catch (e) {
logger.error('Could not convert to AMD module, skipping ' + modulePath);
logger.error('Error was: ' + e);
contents = this.contents;
}
}

deps = findDeps(modulePath, contents);

let context = {pkgsMainMap: {}, config: {shim: {}}};
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"aurelia-dependency-injection": "^1.0.0",
"aurelia-logging": "^1.2.0",
"aurelia-polyfills": "^1.0.0",
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
"babel-polyfill": "^6.0.0 || ^7.0.0 || ^8.0.0",
"babel-register": "^6.0.0 || ^7.0.0 || ^8.0.0",
"esprima": "^4.0.0",
Expand Down
33 changes: 33 additions & 0 deletions spec/lib/build/bundled-source.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,39 @@ exports.t = t;
.toBe("define('foo/bar/lo',['require','exports','module','./t'],function (require, exports, module) {var t = require('./t');exports.t = t;});");
});

it('transforms npm package js file in native es module format', () => {
let file = {
path: path.resolve(cwd, 'node_modules/foo/bar/lo.js'),
contents: `
import t from './t';
export {t};
`
};

let bs = new BundledSource(bundler, file);
bs._getProjectRoot = () => 'src';
bs.includedBy = {
includedBy: {
description: {
name: 'foo',
mainId: 'foo/index',
loaderConfig: {
name: 'foo',
path: '../node_modules/foo',
main: 'index'
}
}
}
};
bs._getLoaderPlugins = () => [];
bs._getLoaderConfig = () => ({paths: {}});

let deps = bs.transform();
expect(deps).toEqual(['foo/bar/t']);
expect(bs.requiresTransform).toBe(false);
// assume babel did right job for bs.contents
});

it('transforms npm package js file with named AMD module', () => {
let file = {
path: path.resolve(cwd, 'node_modules/foo/index.js'),
Expand Down

0 comments on commit 1669a6f

Please sign in to comment.