vite icon indicating copy to clipboard operation
vite copied to clipboard

Chunked code runs in wrong order

Open Artur- opened this issue 4 years ago • 8 comments

Describe the bug

With suitable imports, it seems that the following code

import '../utils/boot.js'; // boot.js defines window.JSCompiler_renameProperty

....

   static get observedAttributes() {
     if (!this.hasOwnProperty(JSCompiler_renameProperty('__observedAttributes', this))) {
...

can execute so that observedAttributes is run before the global JSCompiler_renameProperty has been set, resulting in

Uncaught ReferenceError: JSCompiler_renameProperty is not defined
    at Function.get observedAttributes [as observedAttributes] (properties-mixin.js:122)
    at dom-repeat.js:800

This only happens with some specific imports, as shown in the test case.

Reproduction

git clone https://github.com/Artur-/vite-vaadin-problem1.git
cd vite-vaadin-problem1
npm i
npm run dev

Open localhost:3000 and look at the console output. There should be no errors.

System Info

System:
    OS: macOS 11.6
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 290.42 MB / 32.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 16.9.1 - /usr/local/bin/node
    Yarn: 1.22.11 - /usr/local/bin/yarn
    npm: 7.21.1 - /usr/local/bin/npm
    Watchman: 2021.09.13.00 - /usr/local/bin/watchman
  Browsers:
    Brave Browser: 93.1.29.81
    Chrome: 94.0.4606.61
    Chrome Canary: 96.0.4656.3
    Firefox: 92.0
    Safari: 15.0
    Safari Technology Preview: 15.4
  npmPackages:
    vite: ^2.5.4 => 2.6.0

Used Package Manager

npm

Logs

No response

Validations

Artur- avatar Sep 29 '21 19:09 Artur-

Another case, possible with the same cause, is when using iron-icon from https://github.com/PolymerElements/iron-icon/blob/v3.0.1/iron-icon.js

This imports iron-meta https://github.com/PolymerElements/iron-icon/blob/v3.0.1/iron-icon.js#L13

iron-meta.js defines a custom element https://github.com/PolymerElements/iron-meta/blob/v3.0.1/iron-meta.js#L135

Yet when iron-icon creates a <iron-meta> tag https://github.com/PolymerElements/iron-icon/blob/v3.0.1/iron-icon.js#L138, the custom element has not yet been defined.

I was not able to create a reduced test case for this one but it reproduces in one of our application.

Artur- avatar Oct 27 '21 07:10 Artur-

@patak-js Hi, this issue is very important for us to get Vite integration working at Vaadin.

The problem appears to be quite severe: running code in the wrong order may cause unpredictable consequences. Would you have time to look into this issue and maybe give some pointers about the root cause?

web-padawan avatar Oct 27 '21 09:10 web-padawan

I'm not sure it's a bug of Vite. If you just switch these two lines.

https://github.com/Artur-/vite-vaadin-problem1/blob/01c59956297768e4642b1f951ff9bd25c75ca52c/frontend/index.ts#L1-L2

And it works. Maybe the cause it's the difference of "import order" between cjs and esm.

hyf0 avatar Oct 28 '21 11:10 hyf0

A simplified test is

import '@polymer/polymer/polymer-legacy.js';
import "@polymer/polymer/lib/utils/debounce.js";
import '@polymer/polymer/lib/elements/dom-module.js';
import '@polymer/iron-media-query/iron-media-query.js';

Artur- avatar Oct 28 '21 11:10 Artur-

Now what happens in the browser is polymer-legacy.js. becomes

 import {
  Base,
  Polymer,
  html
} from "/@fs/Users/artur/test/vite-vaadin-problem1/node_modules/.vite/chunk-E37EP5WI.js?v=7f8f8d06";
import "/@fs/Users/artur/test/vite-vaadin-problem1/node_modules/.vite/chunk-XMBTGBNN.js?v=7f8f8d06";
import "/@fs/Users/artur/test/vite-vaadin-problem1/node_modules/.vite/chunk-2ZES3KKB.js?v=7f8f8d06";
import "/@fs/Users/artur/test/vite-vaadin-problem1/node_modules/.vite/chunk-T5UZQ2GC.js?v=7f8f8d06";

The chunk E37EP5WI contains the code from iron-media-query.js which means that its side effects are executed first.

The common dependency, which absolutely must be run before, is included in the chunk T5UZQ2GC

// node_modules/@polymer/polymer/lib/utils/boot.js
window.JSCompiler_renameProperty = function(prop, obj) {
  return prop;
};

and that is executed last

Artur- avatar Oct 28 '21 12:10 Artur-

My reproduction and the result is the same with @Artur-

import '@polymer/iron-list/iron-list.js';
import { Debouncer } from "@polymer/polymer/lib/utils/debounce.js";
import '@vaadin/vaadin-grid-pro/theme/lumo/vaadin-grid-pro-edit-column.js';
import '@vaadin/vaadin-lumo-styles/color.js';

hyf0 avatar Oct 28 '21 12:10 hyf0

Minimal reproducible example with esbuild:

esbuild \
  ./node_modules/@polymer/polymer/polymer-legacy.js \
  ./node_modules/@polymer/polymer/lib/utils/debounce.js \
  ./node_modules/@polymer/polymer/lib/elements/dom-module.js \
  ./node_modules/@polymer/iron-media-query/iron-media-query.js \
  --bundle --splitting --outdir=out --format=esm

Maybe related: https://github.com/evanw/esbuild/issues/399

haoqunjiang avatar Oct 28 '21 14:10 haoqunjiang

Is there a way to resolve this ticket faster if the user is allowed to define an order themselves? Let the compiler tell me what conflicts emerge and I will deal with them myself.

WoodrowShigeru avatar May 08 '25 08:05 WoodrowShigeru

I've just had an issue with this topic where my method genericGetJson couldn't be found. Upon looking at the JavaScript file (with minify:false, for debugging), the method declaration was const genericGetJson$1 = …. What would rename the method like that? Is this a feature acting bogus?

I don't know (yet) how to reproduce it, though. I continued debugging and now the issue is something else:

I am importing at one early point like import '@/internal.js'; because I want the whole file to be loaded. It contains all my utilities (i.e. genericGetJson as part of http) and it is an independent module.

However, I've noticed that it doesn't load everything as I'm expecting. I've commented out everything after this early import. Temporarily, nothing happens in my app except for imports. Only if I do a console.log like so …

import * as all from '@/internal.js';
console.log(all.http)

… does the genericGetJson declaration even show up in that file. Is there a "smart" – purposeful, I mean – "only import what you need" detection going on – and how do I disable it? Or how else am I supposed to write the import in order to guarantee that everything gets loaded?

UPDATE: I've found a clumsy workaround that guarantees the loading of all at that point in time.

import * as all from '@/internal.js';
Object.keys(all).length + Object.keys(all).length;

Though, this did not resolve the … somehow? messed up chunk order, so I had to completely deactivate manualChunks.

WoodrowShigeru avatar Aug 05 '25 13:08 WoodrowShigeru