Skip to content

feat: add new optimization.entryIife config#18772

Merged
alexander-akait merged 5 commits intowebpack:mainfrom
fi3ework:entry-iife
Sep 25, 2024
Merged

feat: add new optimization.entryIife config#18772
alexander-akait merged 5 commits intowebpack:mainfrom
fi3ework:entry-iife

Conversation

@fi3ework
Copy link
Contributor

@fi3ework fi3ework commented Sep 17, 2024

What kind of change does this PR introduce?

Fix #18694.

Still need to check the code before ready for review, will check tomorrow.

Did you add tests for your changes?

Yes.

Does this PR introduce a breaking change?

No.

What needs to be documented once your changes are merged?

webpack/webpack.js.org#7402

@webpack-bot
Copy link
Contributor

For maintainers only:

  • This needs to be documented (issue in webpack/webpack.js.org will be filed when merged)
  • This needs to be backported to webpack 4 (issue will be created when merged)

@fi3ework fi3ework marked this pull request as ready for review September 18, 2024 17:57
@fi3ework
Copy link
Contributor Author

@alexander-akait Any review suggestions are welcome, thank you!

@alexander-akait
Copy link
Member

Also if we can optimize iife better in future, make sense to rename option avoidIife or optimizeIife and in future we will improve it better

renamedInlinedModule.get(m) ||
this.renderModule(m, chunkRenderContext, hooks, false);
const renderedModule = renamedInlinedModule
? renamedInlinedModule.get(m)
Copy link
Member

@alexander-akait alexander-akait Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a test here, I think it is unnecessary, because we already renamed them before

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just try

const renderedModule = this.renderModule(
					m,
					chunkRenderContext,
					hooks,
					false
				);

And the output the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a test here, I think it is unnecessary, because we already renamed them before

It's necessary. The initial value of ⁠renamedInlinedModule is false. If ⁠avoidEntryIife is enabled, ⁠getRenamedInlineModule will check for other reasons to bail out of the IIFE. If any exist, ⁠renamedInlinedModule will remain false because the inlined module will still be wrapped in an IIFE for those reasons. Therefore, we skip the optimization here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ask this because of

for (const [m, moduleInfo] of inlinedModulesToInfo) {

Do we really need source.replace? We need a test here, because our tests don't need renaming, so i thought we could avoid this here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't need renaming, we can simplify our code quite a bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fi3ework I still think we have wrong logic, because if I remove

for (const variable of usedInNonInlined) {
				const references = getAllReferences(variable);
				const allIdentifiers = new Set(
					references.map(r => r.identifier).concat(variable.identifiers)
				);

				const newName = this.findNewName(
					variable.name,
					usedNames,
					m.readableIdentifier(runtimeTemplate.requestShortener)
				);
				usedNames.add(newName);
				for (const identifier of allIdentifiers) {
					const r = /** @type {Range} */ (identifier.range);
					const path = getPathInAst(ast, identifier);
					if (path && path.length > 1) {
						const maybeProperty =
							path[1].type === "AssignmentPattern" && path[1].left === path[0]
								? path[2]
								: path[1];
						if (maybeProperty.type === "Property" && maybeProperty.shorthand) {
							source.insert(r[1], `: ${newName}`);
							continue;
						}
					}
					source.replace(r[0], r[1] - 1, newName);
				}
			}

Everything works fine

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said before, we already doing renaming before (in concatination modules) and I don't think we need to do it here

Copy link
Member

@alexander-akait alexander-akait Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just put console.log or use debugger for fast debug and we never reach this branches

We already continue here:

if (usedInNonInlined.size === 0) {
  renamedInlinedModules.set(m, source);
  continue;
}

Copy link
Contributor Author

@fi3ework fi3ework Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The case in test/configCases/output-module/iife-entry-module-with-others/index.js It's not working as well as it should. I'm fixing it. I checked the 'test/cases/entry-inline' case, and it is still working.

I made https://stackblitz.com/edit/node-ojwwax, you could check localVar in dist-5.91.0 and dist-5.94.0 to see the difference. In 5.94.0, localVar is renamed to src_localVar by renaming.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexander-akait Updated, please check the new test case now.
The current test cases serve the following purposes, for instance with iife-entry-module-with-others:

  1. Assert the correct IIFE comment in the bundle.
  2. Assert the correct runtime behavior of the bundle.
  3. If the reason branch it need to be isolated against other entry modules. is deleted, the test will fail

The other test cases are similar, iife-multiple-entry-modules has an extra avoidEntryIife configuration toggle test, which can be seen as a supplement to test/cases/entry-inline.

@fi3ework
Copy link
Contributor Author

Also if we can optimize iife better in future, make sense to rename option avoidIife or optimizeIife and in future we will improve it better

Will this confuse with https://webpack.js.org/configuration/output/#outputiife ? Using optimizeEntryIife will help a little?

@alexander-akait
Copy link
Member

@fi3ework I still think we can get this into a plugin, because we can do more optimization in future (like in todo)

Will this confuse with https://webpack.js.org/configuration/output/#outputiife ? Using optimizeEntryIife will help a little?

Let's skip the name for now, I don't like spending too much time on it, the working code is more important, we need to add tests and check everything above. In fact, we can make more optimizations for iife in the future. I will finish naming.

@alexander-akait
Copy link
Member

@fi3ework I'll merge it now because the logic works completely, but I still think we should have thought about new hooks to bring this logic into the plugin (we always try to do this), I think something like:

const factoryRenderedModule = hooks.optimizeInlinedModule.call(() => this.renderModule(...), m, allModules, ...otherArgs);
const renderedModule = factoryRenderedModule();

So, we can create a map new Map<m, Map<Module, Source>> to store renamedInlinedModules to avoid recalculate it in the each loop interation

What do you think?

@alexander-akait alexander-akait merged commit 4866b0d into webpack:main Sep 25, 2024
@fi3ework
Copy link
Contributor Author

Is it possible to get the non-inlined rendered module result from

const chunkModules = Template.renderChunkModules(
chunkRenderContext,
inlinedModules
? allModules.filter(
m => !(/** @type {Set<Module>} */ (inlinedModules).has(m))
)
: allModules,
module => this.renderModule(module, chunkRenderContext, hooks, true),
prefix
);
so we could avoid using () => this.renderModule(...) and re-render that again?

cc @ahabhgk, could you please take a look at the new proposal for the hook as well? Are there any other issues we can address with this hook in Rspack to make it more general? Thanks! 😊

@ahabhgk
Copy link
Contributor

ahabhgk commented Sep 26, 2024

hooks.optimizeInlinedModule looks good to me

@alexander-akait
Copy link
Member

Looks good for me too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build takes twice as long with >=5.92.0 compared to 5.91.0

5 participants