Unable to load content from Three.js Examples library (Error loading script for "three/examples/jsm/loaders/OBJLoader2")

In my Angular application, I have a simple setup using Three.js. When I try to import the `OBJLoader2` from `three/examples/jsm/loaders/OBJLoader2`, everything works fine except when running it with the `ts_devserver`. The browser console shows an error:

GET http://localhost:4200/three/examples/jsm/loaders/OBJLoader2.js net::ERR_ABORTED 404 (Not Found)
Error: Script error for "three/examples/jsm/loaders/OBJLoader2"
    at makeError (ts_scripts.js?v=03400874:175)
    at HTMLScriptElement.onScriptError (ts_scripts.js?v=03400874:1745)

The imported script cannot be found by the `ts_devserver`, but running in production mode works fine. You can replicate this issue by visiting this link, installing dependencies with `yarn install`, and then running `yarn dev`.

Please note that running `yarn pwa` works without any errors @ http://localhost:8080!

Answer №1

After further investigation, I realized that my previous answer was not entirely accurate as it resulted in the following error:

TypeError: Cannot read property 'Objloader2' of undefined
. This mistake went unnoticed initially because I was focused on the Network tab in the dev console. Despite this error, the file is still returning a 200 status code from the server, which is noteworthy.

The issue stems from the fact that ts_devserver expects only UMD inputs while our script is different. To address this, I attempted to wrap it using npm_umd_bundle:

load("@build_bazel_rules_nodejs//internal/npm_install:npm_umd_bundle.bzl", "npm_umd_bundle")

npm_umd_bundle(
    name = "objloader_umd",
    package_name = "objloader",
    entry_point = "@npm//:node_modules/three/examples/jsm/loaders/OBJLoader2.js",
    package = "@npm//three",
)

and then added it to ts_devserver as a script:

ts_devserver(
  ...,
  scripts = [
    ...,
    ":objloader_umd",
  ],
)

This modification allows us to now import elements from the newly created module objloader!

await import('objloader')

Essentially, this could be the solution. However, for added convenience, let's take one more step. Given that we already have rxjs_shims.js for deep imports with rxjs, let's include another similar script:

// three/examples/jsm/loaders/OBJLoader2 -> objloader
(function (factory) {
  if (typeof module === 'object' && typeof module.exports === 'object') {
    var v = factory(require, exports);
    if (v !== undefined) module.exports = v;
  } else if (typeof define === 'function' && define.amd) {
    define('three/examples/jsm/loaders/OBJLoader2', ['exports', 'objloader'], factory);
  }
})(function (exports, objloader) {
  'use strict';
  Object.keys(objloader).forEach(function (key) {
    exports[key] = objloader[key];
  });
  Object.defineProperty(exports, '__esModule', {value: true});
});

In essence, what this does is create an alias for the import path from

three/examples/jsm/loaders/OBJLoader2
to objloader, particularly for the dev server environment.

With this approach, there is no longer a need to differentiate between development and production builds since imports can remain consistent without altering the TS source code!

Answer №2

Bazel does not currently have the capability to split code (or import JavaScript files lazily) while in development mode.

For more information, check out this resource from their angular-bazel-example. You can also keep up with progress on this issue on Github.

It's important to note that code splitting is not yet available in development mode, so the //src:devserver target will not serve a code split bundle. Any dynamic import() statements will resolve to modules included in the initial JS payload.

Answer №3

It seems like the request is trying to access

http://localhost:4200/three/examples/jsm/loaders/OBJLoader2.js
but cannot find it, which makes sense.

Upon first observation: changing the import path to

// @ts-ignore
await import('npm/node_modules/three/examples/jsm/loaders/OBJLoader2')

successfully resolves the issue! (ts-ignore is necessary to bypass tsc). You do not even need to include any additional_root_paths or other three-related settings in the target.

On the second observation: by adding

"npm/node_modules/three"
to additional_root_paths and adjusting the import to

// @ts-ignore
await import('examples/jsm/loaders/OBJLoader2')

the problem is also resolved.

However, attempting to add "npm/node_modules" similarly does not fix the original import... Disappointing.

So, finding a solution for this import to work in both development and production environments remains unclear. But there is a workaround that I can suggest! Since it is a dynamic import, you can consider using an approach similar to this:

let module;
if (isDev) {
  // @ts-ignore
  module = await import('npm/node_modules/three/examples/jsm/loaders/OBJLoader2')
} else {
  module = await import('three/examples/jsm/loaders/OBJLoader2')
}

I assume you already know how to distinguish between dev and prod builds and can create the isDev variable yourself ;)

Furthermore, it's been mentioned that directly inserting variables into import functions may disrupt static analyzers. Hence, I advise against the following approach:

const prefix = isDev ? 'npm/node_modules/' : '';
const module = await import(`${prefix}examples/jsm/loaders/OBJLoader2`)

Although the if-else statement might be acceptable, as the argument in the import function remains static.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Load information into a different entity

I need help with adding new values to an existing object. When I receive some form data from noteValue, I also have additional input data in my component under person that I would like to integrate into noteValue before saving it. let noteValue = form.va ...

The NgbTooltip fails to display the arrow icon ( ▼ ) within the NgbPopover's window

There appears to be an issue with the arrow div not functioning properly within NgpPopover body due to conflicting arrow classes for NgbPopover's div.arrow and NgbTooltip's div.arrow. This seems to be a known problem in ng-bootstrap when using bo ...

Retrieving Names Using Angular2 Dynamic Component Loader to Render a Component List

I am currently utilizing a Dynamic Component Loader to present a series of components using *ngFor: <div [dragula]='"bag-one"' [dragulaModel]='types'> <div *ngFor="let component of types; let i = index"> <dcl-wrapp ...

Separate the date format string into tokens

I am currently attempting to create a function that is able to transform a date format string such as %d/%m/%Y %H:%n where the variables are always denoted by a percentage sign followed by one character, into an array of tokens: ["%d", "/", "%m", "/", " ...

Angular routing does not properly update to the child's path

I've organized my project's file structure as follows: app/ (contains all automatically built files) app-routing.module.ts components/ layout/ top/ side/ banner/ pages/ ...

Explain a category of instance used in a template parameter

I am currently working on implementing a basic IOC container with type-checking capabilities. My goal is to pass the "register" method an abstract class type along with an instance of a derived type. In the "resolve" function, I aim to provide an abstrac ...

Navigating the store in Ionic Angular using Ngrx

Currently, I am in the process of developing an app using Ionic Angular Cordova. My issue lies in trying to display the state of my application, specifically all the objects within it. However, despite my efforts, the objects that I have added cannot be lo ...

To achieve proper display of multiple boxes, it is essential for each box to be

My current approach involves adding boxes to the scene based on specific dimensions for height, width, and depth, and it works perfectly when the boxes are all square. https://i.sstatic.net/HdDSX.png However, the issue arises when I try to use a rectangu ...

The rotation function of a THREE.js object seems to be malfunctioning

Currently, I am facing an issue with a Blender object that I have successfully displayed on my web page using THREE.js. However, for some reason the object is not rotating when my loop function is called. In my approach to working with JavaScript, I am tr ...

Startling error: Our node server.js running into an unexpected token

I'm attempting to follow the Angular Universal quickstart, but I encountered an error when running "node server.js". Emily's-MBP:vepo Emily$ node server.js /Users/Emily/Development/vepo/server.js:3 import 'angular2-universal/polyfills&apos ...

Having issues getting Angular up and running

I'm having some issues with the global installation of Angular. Below is the error message I received: C:\Users\DevSa\ng -> C:\Users\DevSa\node_modules\@angular\cli\bin\ng > @angular/<a href ...

Angular2+ does not return any elements when using .getElementsByClassName() even if they are present

I have a question that seems simple, but I can't seem to find the answer anywhere. I've looked through past questions but still haven't found a solution... In my Angular template, there is a large amount of text inside a div, and some parts ...

Steps for releasing a third-party library that is compatible with both Angular 2 and Angular 4

Currently, I am utilizing a third-party library for Angular that is compatible with Angular 2. However, I want to make sure this library can support all versions of Angular, including Angular 4 and Angular 5. How can I go about publishing an updated vers ...

Using TypeScript to assign string array values to object properties

I am working with a string array: values: string['myName', 'myLastname', 'myAge'] and my goal is to assign each value to a property of an object like this: myModel={name:'', lastname:'', age:''} o ...

Transition smoothly from the first texture to a solid color, and then seamlessly switch to the second texture using a GLSL Shader

I am working on a GLSL fragment shader that aims to achieve the following sequential effects: Transition from texture 1 to a specific color Transition from the color to texture 2 Here's my initial attempt: // Uniforms uniform sampler2D tex1; uniform ...

Using TypeScript, add an observable to an array of observables using RxJS

Can someone explain how to include Observable<News> in an array of observables? newsArray: Observable<Array<any>>; addNews(newsId: number) { let news = this.newsService.getNewNews(newsId); // this results in an Observable<News> ...

Set the position to fixed so it doesn't scroll

Is there a way to create a fixed position div that remains in place when the user scrolls, similar to the effect shown in this example image? Position Absolute: https://i.sstatic.net/4RAcc.png Position Fixed (desired effect): https://i.sstatic.net/3DIna. ...

The TypeScript compiler is unable to locate the name 'window'

Within my Meteor/React project, I encounter the following line of code: let gameId = window.prompt("Please input the ID of the game you would like to load."); The TypeScript compiler presents an error during transpiling: Cannot find name 'window&apo ...

What is the purpose of having a tsconfig.json file in every subdirectory, even if it just extends the main configuration file?

My goal is to streamline the configuration files in my front-end mono repo by utilizing Vite with React and TypeScript. At the root of my repository, I have set up a tsconfig.json file that contains all the necessary settings to run each project, including ...

What is the best way to configure Jenkins to exclude or include specific component.spec.ts files from being executed during the build

Currently, I am facing an issue while attempting to include my spec.ts files in sonarqube for code coverage analysis. However, my Jenkins build is failing due to specific spec.ts files. Is there a way to exclude these particular spec.ts files and include ...