mjs couse trouble in create-react-app
Opened this issue · 9 comments
It throws Unhandled Rejection (TypeError): __WEBPACK_IMPORTED_MODULE_1_collisions___default.a is not a constructor
If I import Collisions, { Circle, Polygon } from 'collisions';
And console.log(Collisions)
gives /static/media/Collisions.c776ea0e.mjs
Ok it's caused by facebook/create-react-app#3520
create-react-app Failed to compile.
from the readme:
import {Collisions, Circle, Polygon, Point} from 'collisions';
@GrosSacASac Sure I did that, and able to run it on yarn start
, but failed on yarn build
saying Collisions is not a constructor
Is there way I can view your project? This honestly looks specific to create-react-app, but I'm willing to dig deeper if I can reproduce it on my machine.
Also, it looks like the ticket you linked for create-react-app has been merged. Have you updated it to see if it fixes your issue?
Collisions is not a constructor
occurred when I don't apply what https://github.com/facebookincubator/create-react-app/pull/3537/files said.
But when I did what https://github.com/facebookincubator/create-react-app/pull/3537/files said, building it will result in:
yarn build
yarn run v1.3.2
$ node scripts/build.js
Creating an optimized production build...
Failed to compile.
Failed to minify the code from this file:
./node_modules/collisions/src/Collisions.mjs:12
Read more here: http://bit.ly/2tRViJ9
error Command failed with exit code 1.
I think just like what http://bit.ly/2tRViJ9 said, at this early point, package publish to npm probably should still be ES5 ...
Though I don't quite understand why .mjs file can't be minified.
to minify ES6+ file use uglifyjs harmony branch https://github.com/mishoo/UglifyJS2/tree/harmony
Here's what works for me
build.js
/*
*/
"use strict";
const {textFileContentPromiseFromPath, writeTextInFilePromiseFromPathAndString} = require("utilsac");
const rollup = require('rollup');
const rollup_babel = require('rollup-plugin-babel');
const babel = require("babel-core");
const UglifyJSES5 = require("uglify-js");
const UglifyJS = require("uglify-es");
// do not use those because minify mutates options
// const uglifyES5Options = {
// toplevel: true, // could pass in above <script>s for max minifaction with this
// compress: {
// ie8: false, // ie8 (default false) - set to true to support IE8.
// drop_console: true
// },
// output: {
// beautify: false,
// preamble: "/*contact for source*/"
// }
// };
// const uglifyOptions = {
// ecma: 6,
// toplevel: true, // could pass in above <script>s for max minifaction with this
// compress: {
// ie8: false, // ie8 (default false) - set to true to support IE8.
// drop_console: true
// },
// output: {
// beautify: false,
// preamble: "/*contact for source*/"
// }
// }
// entry points
const files = [
"main"
];
async function rollupBundle(inputOptions, outputOptions) {
// create a bundle
const bundle = await rollup.rollup(inputOptions);
//console.log(bundle.imports); // an array of external dependencies
const written = await bundle.write(outputOptions);
return written;
}
// first build <script nomodule src="">
const bundlePromise = Promise.all(files.map(function (fileName) {
/* rollups bundles and transpiles except node_modules imports
*/
const inputOptions = {
input:"",
plugins: [
// also uses .babelrc
rollup_babel({
exclude: 'node_modules/**',
externalHelpers: false
})
]
};
const outputOptions = {
format: "iife",
name: "",
file: ""
};
inputOptions.input = `js/${fileName}.js`;
outputOptions.file = `built/${fileName}-script.js`;
outputOptions.name = `${fileName}`;
return rollupBundle(inputOptions, outputOptions)
}));
bundlePromise.then(function () {
/* transpile the single file bundled ,
this will transpile node_modules imports that are inside the thing
then minify it*/
return Promise.all(files.map(function (fileName) {
return new Promise(function (resolve, reject) {
babel.transformFile(`built/${fileName}-script.js`, {}, function (err, result) {
if (err) {
reject(err);
}
// result; // => { code, map, ast }
writeTextInFilePromiseFromPathAndString(
`built/${fileName}-script.es5.js`,
String(result.code)
).then(resolve);
});
});
})).then(function () {
return Promise.all(files.map(function (fileName) {
return textFileContentPromiseFromPath(`built/${fileName}-script.es5.js`)
.then(function (content) {
return [fileName, content];
});
})).then(function (contents) {
return Promise.all(contents.map(function ([fileName, code]) {
const result = UglifyJSES5.minify(code, {
toplevel: true, // could pass in above <script>s for max minifaction with this
compress: {
ie8: false, // ie8 (default false) - set to true to support IE8.
drop_console: true
},
output: {
beautify: false,
preamble: "/*contact for source*/"
}
});
if (result.error) {
return Promise.reject(result.error);
}
return writeTextInFilePromiseFromPathAndString(
`built/${fileName}-script.es5.min.js`,
result.code
);
}));
});
});
});
// second build <script type="module" src="">
const bundlePromise2 = Promise.all(files.map(function (fileName) {
const inputOptions = {
input:"",
plugins: [
// also uses .
rollup_babel({
babelrc: false,
exclude: 'node_modules/**',
externalHelpers: false,
"plugins": [
"transform-object-rest-spread"
],
"presets": [
// not env
]
})
]
};
// https://rollupjs.org/#core-functionality
const outputOptions = {
format: "es",
name: "",
file: ""
};
inputOptions.input = `js/${fileName}.js`;
outputOptions.file = `built/${fileName}-es-module.js`;
outputOptions.name = `${fileName}`;
return rollupBundle(inputOptions, outputOptions);
}));
bundlePromise2.then(function () {
/* as every browser supporting <script type="module" src="">
also support es2015 we don't need to transpile italics
only minify it*/
return Promise.all(files.map(function (fileName) {
return textFileContentPromiseFromPath(`built/${fileName}-es-module.js`)
.then(function (content) {
return [fileName, content];
});
})).then(function (contents) {
return Promise.all(contents.map(function ([fileName, code]) {
const result = UglifyJS.minify(code, {
ecma: 6,
toplevel: true, // could pass in above <script>s for max minifaction with this
compress: {
ie8: false, // ie8 (default false) - set to true to support IE8.
drop_console: true
},
output: {
beautify: false,
preamble: "/*contact for source*/"
}
});
if (result.error) {
return Promise.reject(result.error);
}
return writeTextInFilePromiseFromPathAndString(
`built/${fileName}-es-module.min.js`,
result.code
);
}));
});
});
package.json preview
(could remove stuff, I was expermenting a bit)
"devDependencies": {
"@babel/core": "^7.0.0-beta.34",
"@babel/preset-env": "^7.0.0-beta.34",
"babel-core": "^6.26.0",
"babel-loader": "^8.0.0-beta.0",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.6.1",
"parcel-bundler": "^1.2.0",
"rollup": "^0.52.1",
"rollup-plugin-babel": "^3.0.2",
"uglify-es": "^3.2.2",
"uglify-js": "^3.2.2",
"webpack": "^3.10.0"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"dom99": "^8.1.0",
"fscreen": "^1.0.2",
"tabbable": "*",
"utilsac": "^5.2.0"
}