Closed 8Observer8 closed 2 years ago
It's an issue with your bundler, please add cannon-es as a dependency and make sure it is included by browserify.
I use AMD (Asynchronous Module Definition) and RequireJS instead of Browserify for this example. I added cannon-es as dependency. You can look it here. I made the same example like with cannon. cannon works but cannot does not work with the same settings. I added a link to the hello-cannon-es-ts in the topic.
requirejs.config({
baseUrl: "js",
paths: {
"cannon-es": "https://cdn.jsdelivr.net/npm/cannon-es@0.18.0/dist/cannon-es.cjs.min"
}
});
requirejs(["main"], () => { });
It does not work because that's a commonjs module. You need an umd module to make it work with RequireJS.
Cannon-es does not expose an umd module. Please use esmodules directly or alternatively use any bundler.
Thank you very much. I will try later and I will write here about some result.
It's sad that Cannon-es doesn't work like this:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/cannon-es@0.18.0/dist/cannon-es.js"></script>
</head>
<body>
<script>
const gravity = new CANNON.Vec3(0, -9.82, 0);
console.log(gravity);
</script>
</body>
</html>
I receive these errors:
Uncaught SyntaxError: Unexpected token 'export'
Uncaught ReferenceError: CANNON is not defined
But the original Cannon.js works very well:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/cannon@0.6.2/build/cannon.min.js"></script>
</head>
<body>
<script>
const gravity = new CANNON.Vec3(0, -9.82, 0);
console.log(gravity);
</script>
</body>
</html>
I receive these errors:
Wow! I found how to solve these errors in this tutorial: https://sbcode.net/threejs/physics-cannonjs/ I just need to add type="module"
as a script attribute:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<script type="module">
import * as CANNON from "https://cdn.jsdelivr.net/npm/cannon-es@0.18.0/dist/cannon-es.js";
const gravity = new CANNON.Vec3(0, -9.82, 0);
console.log(gravity);
</script>
</body>
</html>
Output:
Vec3Â {x: 0, y: -9.82, z: 0}
It's sad that Cannon-es doesn't work like this
Sorry, I see now that the Cannon-es examples https://github.com/pmndrs/cannon-es/tree/master/examples already work like this - they have the type="module"
script attribute.
It's an issue with your bundler, please add cannon-es as a dependency and make sure it is included by browserify.
Cannon-es works with Browserify and TypeScript without problems. I need to solve the problem with Require.js and AMD.
It does not work because that's a commonjs module. You need an umd module to make it work with RequireJS.
I will try to use UMD. When I try just replace "AMD" to "UMD" it says that ReferenceError: exports is not defined
:
tsconfigs/tsconfig.debug.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "UMD",
"sourceMap": true,
"types": [
"cannon-es",
"requirejs"
]
}
}
tsconfigs/tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"outDir": "../public/js"
},
"include": [
"../src/client/**/*.ts"
]
}
tsconfigs/tsconfig.release.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"sourceMap": false,
"types": [
"node"
]
},
"exclude": [
"../src/client/requireConfig.ts"
]
}
src/client/requireConfig.ts
requirejs.config({
baseUrl: "js",
paths: {
"cannon-es": "https://cdn.jsdelivr.net/npm/cannon-es@0.18.0/dist/cannon-es.cjs.min"
}
});
requirejs(["main"], () => { });
src/client/main.ts
import * as CANNON from "cannon-es";
// import "cannon-es";
function main()
{
const physicsWorld = new CANNON.World();
physicsWorld.gravity.set(0, -9.82, 0);
console.log("gravity = ", physicsWorld.gravity);
const outputElement = document.getElementById("output");
outputElement.innerHTML = "gravity = " + physicsWorld.gravity;
}
// Debug
main();
// Release
// window.onload = () => main();
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>Hello Cannon-ES. TypeScript</title>
<!-- Debug -->
<script data-main="js/requireConfig"
src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
<!-- Release -->
<!-- <script src="js/bundle.min.js"></script> -->
</head>
<body>
<div id="output"></div>
</body>
</html>
package.json
{
"name": "hello-cannon-es-ts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"debug": "tsc -p tsconfigs/tsconfig.debug.json",
"compile": "tsc -p tsconfigs/tsconfig.release.json",
"bundle": "browserify public/js/main.js -o public/js/bundle.js",
"minify": "uglifyjs public/js/bundle.js -o public/js/bundle.min.js",
"release": "npm run compile && npm run bundle && npm run minify"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cannon-es": "^0.18.0",
"requirejs": "^2.3.6"
},
"devDependencies": {
"@types/requirejs": "^2.1.32"
}
}
I just need to add type="module" as a script attribute
Yeah, that's how es modules work (cannon-es is an es module). Read more about it here
I need to solve the problem with Require.js and AMD.
My advice would be to stop using Require.js, it's an antiquated library and has been made obsolete with the introduction of es modules.
Closing since this is not related to cannon-es.
Solution 1. Rollup
I copied the rollup.config.js
file from the cannon-es
folder: https://github.com/pmndrs/cannon-es/blob/master/rollup.config.js I installed rollup
globally using the command: npm i -g rollup
. I installed these packages in the root of my "Projects" directory: npm i -D @babel/core @babel/preset-env @babel/preset-typescript @rollup/plugin-babel @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-replace rollup-plugin-filesize
. TypeScript was installed globally too.
My examples do not have include the node_modules
folder and it saves a lot of space on my laptop because all those packages for rollup
require 35 MB. For example I have this example Projects/my-example-cannonesjs-webgl-ts
and this example has the package.json
file with dependencies and so on, but it does not have the node_modules
folder, it uses Projects/node_modules
on the level above. I just copy names of dependencies to the package.json
file to every example folder in the Projects
folder.
I changed paths to my paths and I deleted what is unnecessary. Use the 'rollup -c' to create a bundle. I added sourcemap: true
to output
to be able to set breakpoints in VSCode.
rollup.config.js
import babel from '@rollup/plugin-babel'
import resolve from '@rollup/plugin-node-resolve'
import json from '@rollup/plugin-json'
// import replace from '@rollup/plugin-replace'
import filesize from 'rollup-plugin-filesize'
const extensions = ['.ts']
const babelOptions = {
babelrc: false,
extensions,
exclude: '**/node_modules/**',
babelHelpers: 'bundled',
presets: [
[
'@babel/preset-env',
{
loose: true,
modules: false,
targets: '>1%, not dead, not ie 11, not op_mini all',
},
],
'@babel/preset-typescript',
],
}
export default [
{
input: `./src/client/main.ts`,
output: { file: `public/js/bundle.js`, format: 'esm', sourcemap: true },
plugins: [json(), resolve({ extensions }), babel(babelOptions), filesize()],
},
// {
// input: `./src/client/main.ts`,
// output: { file: `dist/cannon-es.cjs.js`, format: 'cjs' },
// plugins: [
// json(),
// resolve({ extensions }),
// babel(babelOptions),
// replace({
// // Use node built-in performance.now in commonjs environments
// 'globalThis.performance': `require('perf_hooks') && require('perf_hooks').performance`,
// }),
// filesize(),
// ],
// },
]
Solution 2. Browserify and UglifyJS
npm i -g browserify uglify-js typescript
npm i -D tsify
"scripts": {
"debug": "browserify src/client/main.ts -p tsify --debug -o public/js/bundle.js",
"bundle-release": "browserify src/client/main.ts -p tsify -o public/js/temp-bundle.js",
"minify-release": "uglifyjs public/js/temp-bundle.js -o public/js/bundle.js",
"release": "npm run bundle-release && npm run minify-release"
}
<script src="js/bundle.js"></script>
npm run debug
. You can set breakpoints in your browser in TypeScript files but I cannot set breakpoints in VSCode with the deprecated Chrome Extension from Microsoftnpm run release
. Your application will be compressed to bundle.js
But the main problem was not solved. My main goal is to place my TypeScript examples with cannon-es on some Playground like I made it with Cannon.js, Require.js, glMatrix and pure WebGL: https://plnkr.co/edit/ZrG1OFKjOyxsFbr3?preview
Plunker and Require.js allow to run Jasmine Unit Tests in TypeScirpt: https://plnkr.co/edit/77Ex6gPTBxQyyXNML9tk?preview
Maybe someone knows how to run cannon-es with TypeScript on Plunker or on another playground with any bundler. Please, publish links on examples with cannon-es and TypeScript on some playgrounds.
Maybe this information will help someone. Rollup works fine with TypeScript, Three.js, Cannon-es, and OrbitControls.
Debugging command: rollup -cmw
where: -c
- create a bundle, -m
- debug mode, -w
- watch)
Release commands:
rollup -c
uglifyjs public/js/bundle.js -o public/js/bundle.min.js
I edited the rollup.config.js
script from cannon-es
(cannon-es
is written in TypeScript): https://github.com/pmndrs/cannon-es/blob/master/rollup.config.js
rollup.config.js
import babel from "@rollup/plugin-babel";
import resolve from "@rollup/plugin-node-resolve";
import filesize from "rollup-plugin-filesize";
const extensions = [".ts"];
const babelOptions = {
babelrc: false,
extensions,
exclude: "**/node_modules/**",
babelHelpers: "bundled",
presets: [
[
"@babel/preset-env",
{
loose: true,
modules: false,
targets: ">1%, not dead, not ie 11, not op_mini all",
},
],
"@babel/preset-typescript",
],
};
export default {
input: "./src/main.ts",
output: { file: "public/js/bundle.js" },
plugins: [ resolve({ extensions }), babel(babelOptions), filesize() ]
}
src/main.ts
import * as THREE from "three";
import * as CANNON from "cannon-es";
import { ColladaLoader } from "../../../../node_modules/three/examples/jsm/loaders/ColladaLoader";
import { OrbitControls } from "../../../../node_modules/three/examples/jsm/controls/OrbitControls.js";
console.log(new THREE.Vector3(1, 2, 3));
const world = new CANNON.World( {gravity: new CANNON.Vec3(0, -9.8, 0)} );
console.log("gravity: ", world.gravity);
const loader = new ColladaLoader();
console.log(loader);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderCanvas = document.getElementById("renderCanvas");
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas: renderCanvas });
renderer.setSize(window.innerWidth, window.innerHeight);
const orbitControls = new OrbitControls(camera, renderer.domElement);
orbitControls.target = new THREE.Vector3(0, 0, 0);
console.log(orbitControls);
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>
<canvas id="renderCanvas"></canvas>
<script src="js/bundle.js"></script>
</body>
</html>
I have a very simple TypeScript example in cannon that just print a gravity:
You can run it on playground: https://plnkr.co/edit/EoxKFFYZgtXnTTEX?preview
Source code on GitHub with cannon: https://github.com/8Observer8/hello-cannon-ts Source code on GitHub with cannon-es: https://github.com/8Observer8/hello-cannon-es-ts
When I try to change "cannon" to "cannon-es", for example, this line:
on this line:
I get this error:
Uncaught ReferenceError: exports is not defined
and this error:Uncaught TypeError: Cannot read property 'World' of undefined