How to selectively import specific modules in three.js using ES6 syntax

I recently integrated the three.js library using NPM with the goal of leveraging its new ES6 modular architecture. This design allows for selective importation of specific modules as outlined in this resource: Threejs - Import via modules.

For bundling and transpiling, I am utilizing a combination of gulp, browserify, and babel. Here is a snippet from my build process:

gulp.task("build_js", () => {

return browserify({
    entries: "./public/app/app.js",
    cache: {},
    dev: true
})
    .transform(babelify, {presets: ["env"], plugins: ["syntax-async-functions", "transform-async-to-generator"], sourceMaps: true})
    .bundle()
    .pipe(source("app.bundle.min.js"))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: mode}))
    .pipe(uglify())
    .pipe(sourcemaps.write("./"))
    .pipe(gulp.dest(config.build.js))

});

My objective is to optimize bundle size by importing only necessary modules. However, my observation is that regardless of selecting individual modules or importing all of them, the bundle size remains the same.

For instance, importing all modules in app.js results in a 500Kb bundle:

// app.js

import * as THREE from 'three'; // approximately 500 Kb

On the other hand, attempting to import just one module with ES6 syntax yields an identical bundle size (indicating that all modules are still being imported):

// app.js

import { Vector3 } from 'three'; // also around 500 Kb

Alternative approaches were tested as well:

// app.js

import { Vector3 } from "three/build/three.module.js";

This resulted in the following error:

SyntaxError: 'import' and 'export' may only appear at the top level (45590:0) while parsing /Users/revy/proj001/node_modules/three/build/three.module.js

Therefore, my question arises: how can I effectively import only required modules and maintain a compact bundle size?

Answer №1

It appears that you may not be familiar with the concept of Tree Shaking.

When you use named imports in your modules, other unused modules are not automatically removed from the bundle. The bundler includes all modules in the code regardless of what you have imported by name.

The unused modules, known as dead code, remain in the bundle even though they are not being called by your code.

To eliminate this unnecessary code and reduce the size of your bundle, you will need a minifier that can remove dead code effectively.

You might want to explore the common-shakeify plugin for browserify, which is designed to help with tree shaking:

https://github.com/browserify/common-shakeify

Answer №2

Utilized rollupify in a browserify transform to optimize code by performing tree shaking and removing dead code:

gulp.task("build_js", () => {

return browserify({
    entries: "./public/app/app.js",
    cache: {},
    dev: true
})
    .transform(rollupify, {config: {}})    // <---
    .transform(babelify, {presets: ["env"], plugins: ["syntax-async-functions", "transform-async-to-generator"], sourceMaps: true})
    .bundle()
    .pipe(source("app.bundle.min.js"))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: mode}))
    .pipe(uglify())
    .pipe(sourcemaps.write("./"))
    .pipe(gulp.dest(config.build.js))

});

}

Would love to understand why ES6 module import behaves the way it does..

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

Develop a client-side API utilizing various libraries

After completing the server side of an API that delivers HTML via JSON using REST through CodeIgniter, I am now exploring how to create a client-side API with JavaScript. The goal is to retrieve data from the server through the API, display it in the DOM, ...

Dealing with Memory Issues in Google Apps Scripts

Currently, I am addressing a challenge within my organization that requires me to maintain some level of ambiguity. However, I have been granted permission to discuss this issue openly. The task at hand involves creating a script to analyze a Google Sheet ...

Error in THREE.js: Unable to access property 'lib' from an undefined source (THREE.ShaderUtils.lib["normal"])

I have been working on the challenges provided in the WebGL introductory book by Oreilly. Encountered a runtime error with the following code snippet. After searching online, it seems like I am the only one facing this issue. Could you please assist me in ...

Is there a way to make Express.js pass parameters with special characters exactly as they are?

I am currently working on a project within the freeCodeCamp "API and Microservices" curriculum that involves using Express.js to handle routes. The project itself is relatively straightforward, with some pre-defined routes and others that need to be creat ...

Discontinue playing videos embedded in iframes on Dailymotion

I'm currently working on creating a slider that includes videos from multiple providers, and I need to ensure that the videos stop when changing slides. So far, I've successfully implemented this feature for Vimeo and YouTube without making any a ...

Preserve HTML element states upon refreshing the page

On my webpage, I have draggable and resizable DIVs that I want to save the state of so they remain the same after a page refresh. This functionality is seen in features like Facebook chat where open windows remain open even after refreshing the page. Can ...

What is the mechanism behind the functionality of the input type=number spinner in browsers?

I want to recreate the spinner feature found in input type=number. <input type=number step=0.3/> When clicking on the up arrow of the spinner, the value increases by 0.3 (0.3, 0.6 , 0.9 , 1.2 , 1.5 ...etc). However, if the current value is 1.4 and ...

AdonisJs experiencing issues with web socket.io functionality

Having trouble with Web socket.io in AdonisJs. I have been using a library called adonis5-scheduler to run tasks within Adonis. Shown below is one of my tasks: import { BaseTask } from 'adonis5-scheduler/build' export default class GetRoulette ...

Converting counterup2 to pure vanilla JavaScript: step-by-step guide

Is there a way to convert the counterUp2 jQuery code to vanilla JavaScript? const counters = document.querySelectorAll('.counter'); function count(element) { let currentValue = 0; const targetValue = parseInt(element.innerText); let interv ...

jQuery floating sidebar that dynamically adjusts position based on content overflow

I've come across an interesting scenario with a fiddle that I'm working on: http://jsfiddle.net/yFjtt/1/ The main concept is to allow users to scroll past the header and have the sidebar 'stick' in place as they continue scrolling down ...

Is there a method in Express to verify which URL a post is being sent to?

At the moment, I am using express to proxy my session creation URL in the following manner: app.post('/sessions', (req, res) => { // Code goes here }) The code that is used for this proxy also needs to be applied to my /confirmation endpoi ...

Retrieving JSON data with jQuery's Ajax functionality

I'm currently developing a web application to handle the administrative tasks for a restaurant. The main functionalities include creating new orders, adding order items, and managing financial overviews. One of the key features is the ability to view ...

Display the current count of selected radio buttons in real-time

I am working with radio buttons that are generated dynamically using a 2D array within a while loop. I want to display the number of radio buttons checked when one is clicked. Here are my radio buttons: $n=0; while($row=mysqli_fetch_row($rs)){?> <f ...

"Switching Classes with a Click Event: A Step-by-

This script is designed to work with SoundCloud's widget in order to enable remote text buttons. I am attempting to modify it so that it functions as a remote for an image button that toggles between different pictures for pause and play, rather than ...

Unable to display bar chart on PHP webpage showing database number volumes using JavaScript

I'm currently working on generating a bar chart to show the number of bookings per month. I have two separate SQL queries that retrieve the data correctly, as confirmed by testing. However, when I try to run the file in my browser, nothing is displaye ...

What are the best strategies for handling complex task operations in Node.js Express.js?

How can I effectively manage lengthy task functions in Node.js Express.js to prevent timeout errors? Currently, my application includes a time-consuming function that does not require an immediate response but still needs to execute its tasks. How can I en ...

Display the username on a Meteor React component

I'm facing an issue with one of my React components, which serves as the main layout for my application. It includes a navigation bar that displays the username of the currently logged-in user. The problem arises when Meteor.user() returns undefined d ...

Issue with JSONP request in jQuery/AJAX

I am currently attempting to make a request to a different site, which requires authentication through a cookie. Oddly enough, when I try making the call like this : $.getJSON(url + '?', function(data){ alert(data); }); The HTTP headers do ...

In Javascript, assign default values to an array and update them with new values upon the click of a

My goal is to create a quiz that populates an array. Initially, the quiz is empty but I aim to assign it a default value. This serves as my question navigation: /** * * @param {int} question * @returns {QuizPart} ...

Avoiding URL images on 404 errors in frontend applications

My goal is to dynamically implement images (from image_url_1.jpg to image_url_5.jpg) based on a specific URL. While everything works fine, I encounter an issue when a particular image, like "image_url_4.jpg," is not available and results in a 404 Error cau ...