How to properly combine aframe, threeJS, npm, and webpack? - node.js

I am trying to understand the expected way to set up an AFRAME project and use npm/webpack to install dependencies, including things like three/addons.
I am new to node (and especially webpack), but I have a package.json set up to run a simple server:
{
"name": "test",
"version": "0.0.1",
"description": "test",
"main": "server.js",
"scripts": {
"start": "node server.js",
},
"dependencies": {
"aframe": "^1.3.0"
}
"engines": {
"node": ">=16"
}
}
In my /public directory, I have several html files + js files in various nested directories which use AFRAME (which I was previously loading from CDN).
What's the "right" way to give these scripts access to AFRAME without CDN? What about three, three/addons, or any other ThreeJS/AFRAME npm package?
I gather that I need to use webpack? Can I configure webpack to generate a single bundle.js file that includes all of my dependencies, and then import as desired from that? I don't fully understand the relationship between webpack's bundling and ES6 imports, or how to configure webpack in this way.
Thank you!
EDIT: based on the comments below, here is my package.json now:
{
"name": "test",
"version": "0.0.1",
"description": "test",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"aframe": "git://github.com/aframevr/aframe.git#54022b80c60b12dc755f4f4a71a779b410dd23d0",
"aframe-htmlembed-component": "^1.0.0",
"aframe-extras": "^6.1.1",
"aframe-instanced-mesh": "^0.6.1",
"networked-aframe": "^0.11.0",
"#react-three/drei": "^9.46.3"
},
"devDependencies": {
"webpack": "^5.75.0",
"webpack-cli": "^5.0.0"
},
"engines": {
"node": ">=16"
}
}
webpack.config.js:
// From: https://github.com/Chabloz/a-frame-webpack-boilerplate
const path = require("path");
const config = {
mode: "development",
devtool: "inline-source-map",
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public/dist")
},
watch: false,
resolve: {
modules: [
path.resolve("./src"),
path.resolve("./node_modules")
]
},
externals: {
three: "THREE"
}
};
module.exports = (env, argv) => {
return config;
};
and /src/main.js:
// AFRAME
require("aframe");
// Helpers
require("aframe-htmlembed-component");
require("aframe-extras");
require("aframe-instanced-mesh/src/instanced-mesh");
require("#react-three/drei");
// NAF
require("networked-aframe");
This sucessfully generates /public/dist/bundle.js when I run webpack, and I can include it like so:
<script src="/dist/bundle.js"></script>
But when I try to import any of the modules in the bundle from another script (import * as THREE from "three"), I get Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".. If I change it to import * as THREE from "/dist/bundle.js", I get bundle.js:36779 Uncaught Error: A a-node type is already registered

Related

Jest: node.js SyntaxError: Cannot use import statement outside a module

I have just started learning jest testing and created a sample application to get familiar with jest testing. However, I am getting following error...
Language.js
const calculateTip = (total, percentage) => {
return total + ((percentage / 100) * total) + 1;
};
export {
calculateTip,
}
package.json
{
"dependencies": {
"express": "^4.18.2"
},
"type": "module",
"main": "src/app.js",
"scripts": {
"start": "node src/app.js",
"test": "cls && env-cmd -f ./envs/test.env jest --watchAll"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"jest": "^29.2.2",
"supertest": "^6.3.1"
}
}
I have tried googling for the solution but no luck so far.
Node.js supports esm syntax only from v16, but jest doesn't support it yet.
Therefore, you have 2 choices:
Don't use the esm syntax (import / export)
Add jest-babel with it's config to transpile (convert) esm syntax to cjs one.
You can fix it by installing jest-babel and then creating babel.config.cjs in your root directory and pasting the following into it:
//babel.config.cjs
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
...
//package.json
"type": "module"
//tsconfig.json
...
"target": "esnext",
"module": "commonjs",
...

How to use TypeScript with Sequelize when targeting ESM

I have the following project:
package.json:
{
"name": "ts-sequelize-node-fetch",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "main.js",
"scripts": {
"build": "tsc",
"start": "node dist/main.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#types/validator": "^13.6.3",
"typescript": "^4.4.3"
},
"dependencies": {
"node-fetch": "^3.0.0",
"sequelize": "^6.6.5",
"sqlite3": "^5.0.2"
}
}
tsconfig.json:
{
"compilerOptions": {
"target": "esnext",
"module": "ESNext",
"strict": true,
"moduleResolution": "node",
"outDir": "dist",
}
}
main.ts:
import fetch from "node-fetch";
import { Sequelize, DataTypes } from "sequelize";
const response = await fetch("https://google.com");
console.log(response.status);
const db = new Sequelize({
dialect: "sqlite",
storage: ":memory:"
});
console.log(DataTypes.BLOB);
try {
await db.authenticate();
console.log("DB connection established");
} catch(e) {
console.error("Unable to connect to the database");
}
When I run this (npm run build && npm start) I get the following error:
import { Sequelize, DataTypes } from "sequelize";
^^^^^^^^^
SyntaxError: Named export 'DataTypes' not found. The requested module 'sequelize' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'sequelize';
const { Sequelize, DataTypes } = pkg;
Now I don't get any lint errors in the editor to suggest the changes from the error message so I would assume main.ts should run fine. The code does work if I make the suggested changes from the error message but it would be nicer if we got the error in the editor (or when running tsc) rather than during runtime, or if it is possible for typescript to compile this to working javascript.
I've been struggling with this for years but always found one way or another which allowed typescript to target commonjs. But now when more and more packages only distribute ESM versions (eg. node-fetch and tinyhttp) I really need to find a solution to this.
Are there any typescript options or node flags so typescript can compile this to working javascript or maybe eslint rules to at least show the error in the editor? Should the code even compile if it doesn't run?
I don't know if you still have this issue, but I did.
I manage to solve it by updating all my modules. In my case, this also meant updating sequelize to version 6.23.2.
So in my package.json, I now have this:
{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"compile": "tsc",
"start": "npm run compile && nodemon ./build/index.js",
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.1",
"nodemon": "^2.0.20",
"pg": "^8.8.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.23.2",
"sqlite3": "^5.1.1",
"typescript": "^4.8.4"
}
}
and on my tsconfig.json
{
"buildOptions": {
},
"compilerOptions": {
"outDir": "build",
"target": "ES2017",
"module": "ESNext",
"moduleResolution": "node",
},
}
and I had no other importing errors regarding sequelize.
By the way, if you want to follow this hint, here's how you can update your node modules - or how I did it, anyway.

Webpack can't find module css-loader (Error: Cannot find module '.../webpack_tutorial/node_modules/css-loader/dist/cjs.js')

I'm currently learning webpack with the following tutorial on YouTube: https://www.youtube.com/watch?v=MpGLUVbqoYQ&t=1337s&ab_channel=freeCodeCamp.org, i'm on minute 43.
I want that Webpack loads my css, but when I run "node start", and the error "Cannot find module css-loader" occurs, although I have it installed properly.
This is my webpack.config.js:
const path = require('path');
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.css$/,
use: ["css-loader"]
},
],
}
}
package.json:
{
"name": "webpack_tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack --config webpack.config.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"webpack": "^5.9.0",
"webpack-cli": "^4.2.0"
},
"devDependencies": {
"css-loader": "^5.0.1",
"style-loader": "^2.0.0"
}
}
index.js:
import { run } from "./app/app";
import "./main.css";
import { AlertService } from "./app/alert.service";
import { ComponentService } from "./app/component.service";
const alertService = new AlertService();
const componentService = new ComponentService();
run(alertService, componentService);
Folder structure:
dist
node_modules
src
app
some other files...
index.js
main.css
package.json
webpack.config.js
Has anyone an idea why webpack is not finding this package?

webpack-dev-server does not create initial bundle on start

I have built a basic babel webpack starter project that i clone from git. The git repository has no dest/output/build folder nor does it have any initial build files. I am knew to webpack so i assumed that when the webpack-dev-server started up it would create a folder (in my case 'build') and do a first time compilation of the source files. Instead i am forced to start the process manually only then after the initial compilation will webpack-dev-server compile the changes.
What am i missing ?
package.json
{
"name": "babel-webpack-starter",
"version": "1.0.0",
"description": "A Babel Webpack Stater Pack for compiling ES2015/ES6, ES2016/ES7 and ES2017 code doen to ES5. This will allow for the use of ES6 modules and later ECMAScript features such as async/await. Also includes a webpack-dev-server to auto load server without having to re-compile.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --mode=development",
"start": "webpack-dev-server --output-public-path=/build/ --mode=development"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"webpack": "^4.16.4",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}
webpack.config.js
// Load Node modules
const path = require('path');
// Export modules
module.exports = {
entry: {
app: './src/app.js'
},
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js'
},
module: {
rules: [{
test: /\.js?$/,
exclude: '/node_modules',
loader: 'babel-loader',
query: {
presets: ['env']
}
}]
}
};
webpack-dev-server will not put your app.bundle.js in your working directory, it will compile your files in-memory.
If you want to access the files, add public path to the output option or which you have done there in the npm start script.
output: {
...
publicPath: '/build/'
}
Now, your files will be available in localhost:<port>/build/app.bundle.js
You can check this site out for more information

How to get Grunt working..?

I have read a lot of different posts before asking here but I can't get through that error "Uglify not found"..
I have downloaded node.js, uglfy.js.. Shortly I have followed all the steps here..
How to install grunt and how to build script with it
my Gruntjs file:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
build: {
src: 'js/global.js',
dest: 'js/build/global.min.js'
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['uglify']);
};
and package.json:
{
"name": "contentImageSlider",
"version": "0.1.0",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-concat": "^0.4.0",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-nodeunit": "~0.3.3",
"grunt-contrib-uglify": "~0.4.0"
},
"description": "slider",
"main": "Gruntfile.js",
"dependencies": {
"grunt": "^0.4.5"
},
"scripts": {
"test": "test"
},
"repository": {
"type": "git",
"url": "https://github.com/haldunatar/contentImageSlider.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/haldunatar/contentImageSlider/issues"
},
"homepage": "https://github.com/haldunatar/contentImageSlider"
}
Error :
Local Npm module "grunt-contrib-uglify" not found. is it installed?
Warning:Tast 'uglify' not found. use --force to continue.
Aborted due to warnings.
So every time as I enter "grunt", it gives that error..but I downloaded uglify.js..
Can anybody help me here?
Thanks in advance!
I see that the "grunt-contrib-uglify" is in your package.json file, but the error indicates it's not installed. Perhaps you recently added the dependency but did not perform an npm install? Try running npm install from the root directory, then re-running grunt.

Resources