saharan / OimoPhysics

A cross-platform 3D physics engine
MIT License
863 stars 68 forks source link

Failed to build a simple TypeScript example with Browserify #52

Closed 8Observer8 closed 4 months ago

8Observer8 commented 2 years ago

oimophysics 1.2.2: https://www.npmjs.com/package/oimophysics/v/1.2.2

My example (see source below) works with Parcel but does not work with Browserify.

Error log:

` E:_Projects\Physics\oimo\oimo-debug-drawer-webgl-ts>npm run release

oimo-debug-drawer-webgl-ts@1.0.0 release E:_Projects\Physics\oimo\oimo-debug-drawer-webgl-ts npm run compile && npm run bundle && npm run uglify

oimo-debug-drawer-webgl-ts@1.0.0 compile E:_Projects\Physics\oimo\oimo-debug-drawer-webgl-ts tsc -p tsconfigs/tsconfig.release.json

oimo-debug-drawer-webgl-ts@1.0.0 bundle E:_Projects\Physics\oimo\oimo-debug-drawer-webgl-ts browserify public/js/main.js -o public/js/bundle.js

SyntaxError: 'import' and 'export' may appear only with 'sourceType: module' (54881:0) while parsing E:_Projects\node_modules\oimophysics\OimoPhysics.js while parsing file: E:_Projects\node_modules\oimophysics\OimoPhysics.js at DestroyableTransform.end [as _flush] (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\insert-module-globals\index.js:114:21)
at DestroyableTransform.prefinish (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\readable-stream\lib_stream_transform.js:138:10) at DestroyableTransform.emit (events.js:400:28)
at prefinish (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\readable-stream\lib_stream_writable.js:619:14) at finishMaybe (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\readable-stream\lib_stream_writable.js:627:5) at endWritable (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\readable-stream\lib_stream_writable.js:638:3) at DestroyableTransform.Writable.end (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\readable-stream\lib_stream_writable.js:594:41) at DestroyableTransform.onend (C:\Users\8Observer8\AppData\Roaming\npm\node_modules\browserify\node_modules\readable-stream\lib_stream_readable.js:577:10)
at Object.onceWrapper (events.js:519:28) at DestroyableTransform.emit (events.js:412:35)
npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! oimo-debug-drawer-webgl-ts@1.0.0 bundle: browserify public/js/main.js -o public/js/bundle.js
npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the oimo-debug-drawer-webgl-ts@1.0.0 bundle script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\8Observer8\AppData\Roaming\npm-cache_logs\2022-09-16T11_33_02_421Z-debug.log npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! oimo-debug-drawer-webgl-ts@1.0.0 release: npm run compile && npm run bundle && npm run uglify
npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the oimo-debug-drawer-webgl-ts@1.0.0 release script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\8Observer8\AppData\Roaming\npm-cache_logs\2022-09-16T11_33_02_563Z-debug.log

E:_Projects\Physics\oimo\oimo-debug-drawer-webgl-ts> `

Example. Browserify, UglifyJS, TypeScript were installed globally.

Project structure:

image

Command to build for release: npm run release

package.json

{
  "name": "oimo-debug-drawer-webgl-ts",
  "version": "1.0.0",
  "description": "",
  "main": "public/js/bundle.js",
  "targets": {
    "main": {
       "includeNodeModules": true
    }
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "del_files": "del /f /q /s .\\public\\js\\*.*",
    "dev": "npm run del_files && parcel watch src/main.ts",
    "compile": "tsc -p tsconfigs/tsconfig.release.json",
    "bundle": "browserify public/js/main.js -o public/js/bundle.js",
    "uglify": "uglifyjs public/js/bundle.js -o public/js/bundle.js",
    "release": "npm run compile && npm run bundle && npm run uglify"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "oimophysics": "^1.2.2"
  }
}

tsconfigs/tsconfig.release.json

{
    "compilerOptions": {
        "target": "ES5",
        "outDir": "../public/js",
        "sourceMap": false,
        "types": [
            "node"
        ],
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true
    },
    "include": [
        "../src/**/*.ts"
    ],
    "exclude": [
        "node_modules"
    ]
}

src/main.ts

import { oimo } from "oimophysics";

const oimoWorld = new oimo.dynamics.World();
oimoWorld.setGravity(new oimo.common.Vec3(0, -9.8, 0));

console.log(oimoWorld.getGravity());

public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script type="module" src="js/bundle.js"></script>
</body>

</html>

public/js/main.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var oimophysics_1 = require("oimophysics");
var oimoWorld = new oimophysics_1.oimo.dynamics.World();
oimoWorld.setGravity(new oimophysics_1.oimo.common.Vec3(0, -9.8, 0));
console.log(oimoWorld.getGravity());
8Observer8 commented 4 months ago

I try to use OimoPhysics 1.2.3 with Rollup instead of Browserify.

How to import OimoPhysics using TypeScript?

1)

import "oimophysics";
console.log(new OIMO.Vec3(0, -9.8, 0));

error TS2304: Cannot find name 'OIMO'

2)

import { oimo } from "oimophysics";
console.log(oimo);

SyntaxError: The requested module 'oimophysics' does not provide an export named 'oimo'

3)

import * as OIMO from "oimophysics";
console.log(OIMO);

image

If the third way is right way why I do not see any keywords like for Three.js:

image

8Observer8 commented 4 months ago

So if I try to run this:

import * as OIMO from "oimophysics";
console.log(new OIMO.Vec3(0, -9.8, 0));

I have this error: error TS2339: Property 'Vec3' does not exist on type 'typeof import("E:/_Projects/node_modules/oimophysics/bin/js_modules/OimoPhysics")'

pschroen commented 4 months ago

I can confirm I'm getting the same error with your code, note that the module entry point and typings are pointing here with the namespaces:

https://github.com/saharan/OimoPhysics/blob/68c1ba6395e9eaa6ac482a4387a5c55631008c3c/package.json#L6-L7

There are also index files that re-export the namespaces in the same bin directory.

For example, the following works for me because the package is pointing to the namespaces:

import { oimo } from 'oimophysics';
console.log(new oimo.common.Vec3(0, -9.8, 0));

I've tried changing the package.json entry points to the index files instead, which is what you would expect to work with your code above, though getting a different error with that:

import { Vec3 } from 'oimophysics';
console.log(new Vec3(0, -9.8, 0));
TS2351: This expression is not constructable.
  Type 'Vec3' has no construct signatures.

I'll take a look into the error, though @saharan is the package.json entry points meant to be pointing to the index files instead?

pschroen commented 4 months ago

It would seem that there's been some changes with the TypeScript compiler over the years and simply changing the following line fixes the error for me, for example with Vec3:

https://github.com/saharan/OimoPhysics/blob/68c1ba6395e9eaa6ac482a4387a5c55631008c3c/bin/js_modules/index.d.ts#L24

To include the typeof type operator:

export const Vec3: typeof oimo.common.Vec3;
8Observer8 commented 4 months ago

I load the oimophysics.min.js file using importmap:

    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://8observer8.github.io/libs/es-module-shims@1.10.0/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://8observer8.github.io/libs/gl-matrix@3.4.3/gl-matrix.min.js",
                "oimophysics": "https://8observer8.github.io/libs/oimophysics@1.2.3/oimophysics.min.js"
            }
        }
    </script>

This code compiles without problems:

import { oimo } from 'oimophysics';
console.log(new oimo.common.Vec3(0, -9.8, 0));

But when I run it in the browser I see this error: SyntaxError: The requested module 'oimophysics' does not provide an export named 'oimo' (at bundle.js:2:10)

8Observer8 commented 4 months ago

The same error as above is in the JavaScript example:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
</head>

<body>
    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://8observer8.github.io/libs/es-module-shims@1.10.0/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://8observer8.github.io/libs/gl-matrix@3.4.3/gl-matrix.min.js",
                "oimophysics": "https://8observer8.github.io/libs/oimophysics@1.2.3/oimophysics.min.js"
            }
        }
    </script>

    <script type="module">
        import { oimo } from 'oimophysics';
        console.log(new oimo.common.Vec3(0, -9.8, 0));
    </script>
</body>

</html>
8Observer8 commented 4 months ago

The JavaScript example above works when I import like this: import 'oimophysics'; and use OIMO.Vec3 instead of oimo.common.Vec3:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
</head>

<body>
    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://8observer8.github.io/libs/es-module-shims@1.10.0/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://8observer8.github.io/libs/gl-matrix@3.4.3/gl-matrix.min.js",
                "oimophysics": "https://8observer8.github.io/libs/oimophysics@1.2.3/oimophysics.min.js"
            }
        }
    </script>

    <script type="module">
        // import { oimo } from 'oimophysics';
        // console.log(new oimo.common.Vec3(0, -9.8, 0));

        import 'oimophysics';
        console.log(new OIMO.Vec3(0, -9.8, 0));
    </script>
</body>

</html>
pschroen commented 4 months ago

Ok, there your using your own minified version of the library that's not an ES module and doesn't have any exports in it.

The code import 'oimophysics'; just imports the entire script with window.OIMO in it, which is why that works in your last example.

Compiling the library into your app with TypeScript, and loading the library client side are two different things, and is working as expected there.

Is the original issue still a problem, or can this issue be closed now?

8Observer8 commented 4 months ago

Is it possible to solve it? I think I should use this script: oimophysics\bin\js_modules\OimoPhysics.js

8Observer8 commented 4 months ago

Yes, it is a solution to use js_modules\OimoPhysics.js. I have uploaded it to my GitHub page and renamed to oimophysics.module.js. It is not minified but it is okay. I have minified it using this command:

uglifyjs oimophysics.module.js -o oimophysics.module.min.js

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
</head>

<body>
    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js -->
    <script async src="https://8observer8.github.io/libs/es-module-shims@1.10.0/es-module-shims.js"></script>

    <script type="importmap">
        {
            "imports": {
                "gl-matrix": "https://8observer8.github.io/libs/gl-matrix@3.4.3/gl-matrix.min.js",
                "oimophysics": "https://8observer8.github.io/libs/oimophysics@1.2.3/oimophysics.module.min.js"
            }
        }
    </script>

    <script type="module">
        import { oimo } from 'oimophysics';
        console.log(new oimo.common.Vec3(0, -9.8, 0));

        // import 'oimophysics';
        // console.log(new OIMO.Vec3(0, -9.8, 0));
    </script>
</body>

</html>
pschroen commented 4 months ago

Great, happy you fixed the problem!

I'm using the ES module included in the GitHub repo here in the bin directory as well. That does appear to have a TypeScript issue, but that's unrelated to you importing the library with an importmap.

On the importmap, I should note that browser support is good now since the past year, the shim isn't needed anymore.

And you can also import ES modules directly via an URL, for example:

import { oimo } from 'https://cdn.jsdelivr.net/gh/saharan/OimoPhysics@master/bin/js_modules/OimoPhysics.js';
// or the `v1.2.3` tag for example
import { oimo } from 'https://cdn.jsdelivr.net/gh/saharan/OimoPhysics@v1.2.3/bin/js_modules/OimoPhysics.js';
8Observer8 commented 4 months ago

the shim isn't needed anymore

It is very good! But I think shim can help to run on old computers where browsers are not updated anymore. I have not tested it. Maybe shim will not help in this case. I should test it later. But now I know that I don't need to show it to another people on forums and on playgrounds. I can use shim in my own projects if it will help to run on old computers. Thanks! Now I know why developers of Three.js have deleted shim from the docs: https://threejs.org/docs/#manual/en/introduction/Installation

And you can also import ES modules directly via an URL

I like importmap because if I change a version or a link to a lib on my GitHub Pages I don't need to change it in every file where I import it. I think it is good to see all imports in one place. I like to keep libraries on my GitHub Pages because sometimes jsdelivr doesn't work. I feel calmer this way.

I have tested my TypeScript example with Rollup. It works!

import { oimo } from 'oimophysics';
console.log(new oimo.common.Vec3(0, -9.8, 0));

I will make step by step video tutorials later to practice with OimoPhysics, Three.js, pure WebGL, and spoken English. I will create a topic later here: https://github.com/saharan/OimoPhysics/discussions