Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(node): webpack/terser stripping class names breaking reflection #8784

Merged
merged 1 commit into from Feb 18, 2022
Merged

fix(node): webpack/terser stripping class names breaking reflection #8784

merged 1 commit into from Feb 18, 2022

Conversation

jeremylvln
Copy link
Contributor

@jeremylvln jeremylvln commented Jan 31, 2022

Current Behavior

When building an app with optimization: true, Terser will be instanciated in Webpack's configuration which will apply some optimization mechanisms like minifying the code, etc...

But it will also strip most class names if they are not referenced elsewhere. Thus breaking any reflection mechanism.

Example 1:
In the context of a Nest.js migration using TypeORM, if your migration is as simple as it seems, it will be only referenced when instantiating the Nest's TypeORMModule. As the class is only referenced in the migrations array, Terser will remove the class's name as it seems unneeded. Unfortunately, the class name is used by TypeORM to recognize the migration name and timestamp. TypeORM is blocked.

{"context":"TypeOrmModule","level":"error","message":"Unable to connect to the database. Retrying (1)...","trace":"TypeORMError:  migration name is wrong. Migration class name should have a JavaScript timestamp appended.\n    at new TypeORMError [stripped for readability]"}

Example 2:
Still in a Nest.js context, when using a class as a provider, Nest will use the class name as the provider symbol for further injection. Stripping the class name can either (1) prevent Nest from injecting the provider correctly or, worse (2), inject another class which differs from the one intended.

In my workspace, I've disabled the optimizations by setting optimization: false but Webpack will then produce a development bundle, still interpolating some values like NODE_ENV by hardcoding it to development. This same bundle cannot be used in production because it is well known that some dependencies use conditionals like if (NODE_ENV == 'production'). So my company is blocked: either our apps won't boot or they cannot be deployed to production because their behaviors could be undefined.

IMO, I consider this a critical issue.

Expected Behavior

In the best world, Terser should be smart enough, but this is highly runtime code which is really hard to find statically. Here I'm telling Terser to keep all the class names which will have an impact on the bundle size, but as the current version of Nx is breaking most (to not say all) Nest apps, I consider this a non-issue.

Do not hesitate to challenge my fix proposal, but keep in mind that what can be done on a second time should be done in another PR, to ship this fix ASAP.

To avoid any issue in the future, it could be relevant to add a dummy Nest app as a e2e test to ensure reflection still works.

Related Issue(s)

I guess it fixes #8441 and fixes #8446, but it also shows that #8537 was not fixed properly, I guess this PR fixes it too.

@vercel
Copy link

vercel bot commented Jan 31, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/nrwl/nx-dev/J2u4N7w1s1ReHFor8DfB3vGUA7TD
✅ Preview: Canceled

[Deployment for 6278462 canceled]

@jeremylvln jeremylvln changed the title Prevent Terser from stripping class names breaking reflection fix(node): webpack stripping class names breaking reflection Jan 31, 2022
@jeremylvln jeremylvln changed the title fix(node): webpack stripping class names breaking reflection [critical] fix(node): webpack stripping class names breaking reflection Jan 31, 2022
@jeremylvln jeremylvln changed the title [critical] fix(node): webpack stripping class names breaking reflection fix(node): webpack stripping class names breaking reflection Jan 31, 2022
@jeremylvln jeremylvln changed the title fix(node): webpack stripping class names breaking reflection fix(node): webpack/terser stripping class names breaking reflection Jan 31, 2022
@AgentEnder
Copy link
Member

LGTM 🎉 🚀 . Minification / obfuscation makes less sense on the server anyways, but it certainly shouldn't be there if its breaking things.

@AgentEnder AgentEnder enabled auto-merge (squash) February 10, 2022 18:02
@AgentEnder
Copy link
Member

@IamBlueSlime do you care to try rebasing the PR and pushing it back up? For some reason Circle CI doesn't always kick off that build job.

auto-merge was automatically disabled February 15, 2022 15:10

Head branch was pushed to by a user without write access

@jeremylvln
Copy link
Contributor Author

@IamBlueSlime do you care to try rebasing the PR and pushing it back up? For some reason Circle CI doesn't always kick off that build job.

Done 👌 But no trace of CircleCI :/

Class names are necessary for frameworks using reflection internally.
Like Nest.js which uses reflection when injecting dependency.
@nartc
Copy link
Contributor

nartc commented Feb 18, 2022

@IamBlueSlime I rebased and force-pushed your branch. CI should kick in now.

@AgentEnder AgentEnder merged commit ebeb588 into nrwl:master Feb 18, 2022
aboqasem added a commit to aboqasem/pcs that referenced this pull request Feb 19, 2022
@pemsbr
Copy link
Contributor

pemsbr commented Mar 17, 2022

Hi! Should we also give the same treatment to keep_fnames?

@github-actions
Copy link

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
4 participants