Sinova/Collisions

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

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"
  }