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

Compile legacy and modern builds in a single pass #395

Open
rorticus opened this issue May 6, 2020 · 4 comments
Open

Compile legacy and modern builds in a single pass #395

rorticus opened this issue May 6, 2020 · 4 comments
Assignees

Comments

@rorticus
Copy link
Contributor

rorticus commented May 6, 2020

Instead of building two separate bundles in two separate builds, one legacy and one modern, we should create both bundles in the same build.

@rorticus
Copy link
Contributor Author

Did a bit of a POC on this. You can see it here,

https://differential-loading.now.sh/#home

If you view the source you can see that theres a few new bits in that HTML. Specifically a reference to both bootstrap.js and bootstrap.legacy.js.

Changes

This build required several changes.

cli-build-app

Changes can be seen here.

  • The build now makes two passes, one for modern and one for legacy. It all happens during the same build, just two different compilations.
  • Legacy builds are now suffixed with .legacy to keep them apart from modern builds (since they all exist in the same build space).
  • Added a new plugin, webpack-module-nomodule-plugin to create the appropriate module and nomodule script tags.
  • Because of the new plugin, I had to update html-webpack-plugin.
  • Because of the updated html-webpack-plugin, had to update InsertScriptPlugin to use new hooks.

webpack-contrib

Changes can be seen here. Added a "legacy" option to the build time render plugin, which controls whether or not the plugin uses modern or legacy build files. Build time legacy

Problems

  1. This probably broke watch and serve, given the use of MultiCompiler instead of Compiler. There is also some question on how the stats get merged if there is an error in one of the compiler instances.
  2. The preloaded scripts that get output during BTR don't include the legacy versions. I'm not really sure how the preloads would be directed for modern vs legacy builds.
  3. In theory, the CSS extraction only needs to happen during one of the builds. Extracting the same CSS two times is a waste.
  4. Not sure what to do about manifest.json. Currently generating two, but it seems like regular manifest.json would be enough given that legacy builds aren't meant for environments that can run PWA.

@rorticus
Copy link
Contributor Author

OK! Attempt 2.

POC: https://differential-loading-poc.rorticus.now.sh/#home
Source: https://github.com/rorticus/differential-loading-poc


This approach differs from the last in that instead of using two separate webpack builds, there is only one build. A plugin creates a child compiler to output the modern version. This causes two sets of files to be created:

  • Modern files which end in .modern.js
  • Legacy files end in .js

Changes

Changes to webpack-contrib and cli-build-app were necessary.

cli-buid-app

  • The base config now uses babel-loader to transpile the output into a legacy build.
  • This config is then processed with the BabelEsmPlugin, which has been slightly modified from the the plugin here. The original plugin was modified to completely remove babel-loader rather than just remove its rules.
  • The dist config had to be modified to preserve chunk output names with BabelEsmPlugin.

webpack-contrib

  • Included BabelEsmPlugin mentioned above.
  • Modified BTR to update both modern and legacy versions of the manifest.

Problems

  • No source maps - BabelEsmPlugin currently has a problem outputting source maps.
  • Invalid manifest.json. Both builds (legacy and modern) are creating a file named manifest.json. The latter build wins during the output generating and the manifest for the legacy build is lost to time.
  • Because not all files are in the manifest, BTR was updated to manually search for legacy files (bootstrap and blocks) and manually updates them.
  • The isLegacy flag does more stuff than just javascript. These features would probably need to copied over to BuildEsmPlugin so that the "other" things still happen.

@maier49 maier49 self-assigned this Jun 11, 2020
@maier49
Copy link
Contributor

maier49 commented Jun 17, 2020

I've picked up where Rory left off with the second approach.

I was able to get source maps working by just applying a fix made for them since the original effort to the modified version of the plugin.

The next thing I've been working on is getting externals working, as the original plugin does not support them. Right now I've updated the plugin to apply the externals plugin and it now processes our externals config, but scripts are still not being injected in index.html.

Update: The scripts were not being injected because they were being removed by the ModuleNoModule plugin in base.config.js. However, even after removing that they are still not working. The modern code is still referencing the external by the name of the argument it gets passed in to the code as in the normal bundle, but the wrapping function and logic to retrieve the external dependency are missing. I suspected that the FunctionModulePlugin was the piece missing in this equation but so far am unable to get a working build with that included.

@maier49 maier49 removed their assignment Jun 18, 2020
@maier49 maier49 self-assigned this Aug 26, 2020
@maier49
Copy link
Contributor

maier49 commented Sep 1, 2020

I reworked the babel esm plugin to be a generalized "additional compile" plugin. The results so far seem promising and doesn't force us into using babel. I also updated the API to allow changing loader options as well as adding/removing loaders which enables most of the other legacy vs non legacy differences. There's still some issues to track down like arrow functions appearing in legacy code now.

Changes to webpack-contrib and clil-build-app can be seen here and here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants