question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

--chunk will not work without file --entry_point

See original GitHub issue

The goal is to bundle all of lib/**.js and exports/**.js into the common chunk, and then one bundle for each of the scripts that depend on it. This is harder than expected in practice:

google-closure-compiler --process_common_js_modules --module_resolution NODE  --js lib/**.js --js exports/**.js --chunk common:auto --js testBody.js --chunk body:1:common --js testIndicator.js --chunk indicator:1:common
exports/cli.js:11: ERROR - [JSC_JS_MODULE_LOAD_WARNING] Failed to load module "commander"
  11| import commander from 'commander';

I need to give an --entry_point that points directly to one of the chunks in order to silence the Node module resolution error and get output, which produces two empty chunks and then the compiled output in common.js, containing the compiled output for whichever specific chunk was arbitrarily designated the entry_point. i.e., testBody.js:

google-closure-compiler --process_common_js_modules --module_resolution NODE --entry_point testBody.js  --js lib/**.js --js exports/**.js --chunk common:auto --js testBody.js --chunk body:1:common --js testIndicator.js --chunk indicator:1:common

Produces: body.js - empty indicator.js - empty common.js - equivalent of just having compiled testBody.js

What can I do to get code splitting to work as expected? I have tried using --entry_point ./ but then I cannot set any files in ./ as chunk inputs, as they will throw a duplicate module path error.

The workflow will always look like this, where we are compiling a set of chunks, each with only one dependency (chunk:1:common), and the common chunk will always take input from lib/**.js and exports/**.js. I feel like this is the simplest possible code-splitting setup, and it should be possible to get working.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
brad4dcommented, Sep 24, 2020

OK, I think the problem you’re trying to solve here isn’t the one that chunking is intended for. Chunking is meant to help with building a single, enormous application. That’s why it requires there be a single entry point.

If the N entry points you’re talking about are truly independent applications, then I would encourage you to build them all separately supplying all of the needed sources for each one. If any one of them gets big enough to warrant it, then use chunking to make those load more incrementally.

If they’re really bits of a single application, then I’d encourage you to restructure the application so there is a single entry point.

Why do I say this? It sounds wasteful, right? If you build app A and app B and they share some common libraries, wouldn’t be better to let them share the common code?

Suppose you’ve organized your project to produce these compiled files

  • core.js - shared library code
  • appA.js - entry point and custom logic for application A
  • appB.js - ditto for B

A user has to load all of core.js before loading appA.js in order to use A. However, it’s nearly certain that appA.js doesn’t actually need to use all of the stuff in core.js, so this is loading code they don’t need. As the number of applications and the amount of library code increases, the percentage of code in core.js that appA.js doesn’t need grows also.

If you instead build each application separately, as a single compiled file, the user only has to load that one file that has exactly what is needed in it, with no extras that are only there because some other application you also support uses them.

It’s important to point out that I’m not just talking about individual classes that aren’t needed. closure-compiler can remove unused code paths in individual methods of a library when it can prove that the application will never need them. If you try to compile multiple, logically separate, applications all at once, then the compiler won’t be able to prune the code individually for each one, making both bigger than they should be.

If you remain unconvinced, then this is the way to compile a shared library of code that you can load separately before loading your application.

  1. Define each API your core library supports as externs files. This can include using pre-existing externs files for stuff you just want to use from other open source projects (e.g. underscore or jQuery).
  2. Compile together all of the source code you want in your core library, being sure to give the compiler the externs files for them at the same time, so it won’t remove or rename global variables or properties that are part of the APIs. Note that this means the compiler will have to leave all parts of the API in the final output file, even bits your apps never use.
  3. Compile each of your applications using the source code unique to them and the externs for your core library, again to prevent incorrect optimizations.
  4. Build your application HTML pages in a way that ensures the common library script gets loaded before the actual application script.

Sadly, there’s a bit more to it than that. By default the compiler assumes the output code will run in a more-or-less clean environment that it can feel free to modify by doing things like adding polyfills and defining utility methods used by the output JS code. Loading 2 scripts output by closure-compiler in the same page is almost certain to cause them to step on each other unless you tell the compiler in advance to guard against this. There are a few different options necessary to do this safely, I think one is --isolation_mode=IIFE, and there’s another for specifically isolating polyfills which may be needed in some cases, but I don’t have them at my fingertips just now.

1reaction
brad4dcommented, Sep 23, 2020

@ChadKillingsworth this seems like a good place to plug the tool you’ve been working on to assist with closure-compiler code splitting.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Webpack: emitted chunks do not create a main entrypoint
Webpack: emitted chunks do not create a main entrypoint · It looks like you have cache groups enabled, are you using splitChunks? –...
Read more >
How to Solve the Chunk Load Error in JavaScript - Rollbar
Whenever there's an error observed in dynamically fetching helper JavaScript files known as Chunks, a ChunkLoad Error is thrown.
Read more >
Output - webpack
Note this option does not affect output files for on-demand-loaded chunks. It only affects output files that are initially loaded. For on-demand-loaded chunk...
Read more >
Understanding Webpack's Code Splitting Feature
It does so by scanning your JavaScript code from an entry point (usually ... A big JavaScript bundle.js file can be a problem...
Read more >
Improved Next.js and Gatsby page load performance with ...
Modules not shared in every entry point can be downloaded for routes ... chunk, it loads the code for moduleC even though page1...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found