Skip to content

Code Splitting with System.register and __system_context__.import #15623

Open

Description

@SunHuawei

Feature request

As I don't see the implementation of this in #8833, so I decided to create new issue here.

What is the expected behavior?

  1. Code Splitting with System.register

Given

// webpack.config.js
module.exports = {
  entry: 'entry.js',
  output: {
    libraryTarget: 'system',
  },
  externals: {
    'lodash': 'lodash'
  }
}
// index.js
import('./sub').then((m) => console.log(m));
// sub.js
import _ from 'lodash';
export default _.trim('sub');

Expect

// src_sub_js.js
System.register(["lodash"], function(__WEBPACK_DYNAMIC_EXPORT__, __system_context__) {
...
  1. Convert dynamic import() into a __system_context__.import()

Given

// webpack.config.js
module.exports = {
  entry: 'entry.js',
  output: {
    libraryTarget: 'system',
  },
  externals: {
    'lodash': 'lodash'
  }
}
// index.js
import('lodash').then((m) => console.log(m));

Expect

// main.js
System.register([], function(__WEBPACK_DYNAMIC_EXPORT__, __system_context__) {
...

/***/ "lodash":
/*!********************!*\
  !*** external "lodash" ***!
  \********************/
/***/ ((module) => {

module.exports = __system_context__.import('lodash');

/***/ }),
...

What is motivation or use case for adding/changing the behavior?
This is originally mentioned in #8833. It will improve the performance by lazy loading the required external modules.

How should this be implemented in your opinion?

For the first case, I think we should add a new case system-register into https://github.com/webpack/webpack/blob/main/lib/WebpackOptionsApply.js#L184. And probably need to copy ArrayPushCallbackChunkFormatPlugin and change accordingly.
For another case, I've done a simple plugin to find all the importCalls, the code looks like this

compiler.hooks.normalModuleFactory.tap(pluginName, (factory) => {
          // 3 cases per https://webpack.js.org/api/normalmodulefactory-hooks/#parser
	['javascript/auto', 'javascript/dynamic', 'javascript/esm'].forEach((type) => {
		factory.hooks.parser.for(type).tap(pluginName, (parser) => {
			parser.hooks.importCall.tap(pluginName, (expression) => {
				// console.log('importCall =', expression.source.value, arguments.length);
				this.importCalls.push(expression.source.value);
			});
		});
	});
});

And I use this webpack config

externals: [
	function ({ request }, callback) {
		if (isExternal(externals, request)) {
			if (myPlugin.importCalls.includes(request)) {
				// Lazy load external dynamic imports.
				callback(null, `promise __system_context__.import("${request}")`);
			} else {
				// Eager load external static imports.
				callback(null, `system ${request}`);
			}
		} else {
			callback();
		}
	}
],

Please confirm if my directions are correct.

Are you willing to work on this yourself?
Yes.

Activity

  1. SunHuawei commented on Apr 13, 2022

    @SunHuawei
    Author

    @joeldenning, @guybedford , @sokra, do you have any input?

  2. webpack-bot commented on Jul 14, 2022

    @webpack-bot
    Contributor

    This issue had no activity for at least three months.

    It's subject to automatic issue closing if there is no activity in the next 15 days.

  3. added
    status: staleNo author response after a needs: request; close candidate
    on Jul 14, 2022
  4. alexander-akait commented on Jul 14, 2022

    @alexander-akait
    Member

    bump

  5. removed
    status: staleNo author response after a needs: request; close candidate
    on Jul 14, 2022
  6. added
    status: staleNo author response after a needs: request; close candidate
    on Oct 13, 2022
  7. webpack-bot commented on Oct 28, 2022

    @webpack-bot
    Contributor

    Issue was closed because of inactivity.

    If you think this is still a valid issue, please file a new issue with additional information.

  8. removed
    status: staleNo author response after a needs: request; close candidate
    on Nov 1, 2022
  9. added
    status: staleNo author response after a needs: request; close candidate
    on Feb 1, 2023
  10. removed
    status: staleNo author response after a needs: request; close candidate
    on Mar 8, 2023
  11. added
    status: staleNo author response after a needs: request; close candidate
    on Jun 8, 2023
  12. MBelniak commented on Oct 31, 2023

    @MBelniak

    I'm interested in this. For now the only option for me is to not treat lodash as external, but having it in a separate chunk. Unfortunately, this disables me to share the external lib between microfrontend applications.

  13. alexander-akait commented on Dec 20, 2023

    @alexander-akait
    Member

    @MBelniak I can reopen, do you want to send a PR?

  14. MBelniak commented on Dec 20, 2023

    @MBelniak

    Rather not soon. I don't code in my free time recently and at work I have a lot of tasks. I'll let you know once I'm free to send a PR.

  15. removed
    status: staleNo author response after a needs: request; close candidate
    on Dec 21, 2023
  16. moved this to Priority - Low in webpack 5/6on Dec 21, 2023
  17. JayVelazquez commented on Mar 15, 2024

    @JayVelazquez

    @SunHuawei Hello, I would like to work on this.

  18. added
    status: staleNo author response after a needs: request; close candidate
    on Jun 14, 2024
  19. SunHuawei commented on Jul 1, 2024

    @SunHuawei
    Author

    It seems closed by webpack-bot without a solution. Would anyone be able to reopen this?
    @JayVelazquez , please help when you can. Thanks.

  20. JayVelazquez commented on Jul 1, 2024

    @JayVelazquez
  21. removed
    status: staleNo author response after a needs: request; close candidate
    on Jul 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions