-
Notifications
You must be signed in to change notification settings - Fork 12k
updating webpack config for differential loading #14015
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the commit description is not nearly descriptive enough. "tweak" could be anything. Please explain the difference in behavior (and also probably state how this is used or not used yet)
see AlexR's preso to the team about commit messages from a couple months back
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
type WebpackConfig = any; // tslint:disable-line |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? either give a local type that matches the shape, or import a correct type, or explain in the //tslint comment why you can't
type WebpackConfig = any; // tslint:disable-line | ||
type WebpackPlugin = any; // tslint:disable-line | ||
|
||
export function updateWebpackConfig(config: WebpackConfig): WebpackConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"update" is not descriptive. could you find a name that says what is the update?
createSubConfigs or something? (what does webpack call it when configs are nested in this way?)
|
||
const tweakPolyfills = (file: string) => { | ||
|
||
// TODO: Do we need an own polyfill file for modern browsers? If yes, where is it created? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when do we plan to fix the TODO? can we figure it out in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question for reviewers: Do we need an own polyfill file for modern browsers? If yes, where is it created? (e. g. by a schematic or by this logic on the fly?)
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs some file-level commenting explaining what's going on, in case the reader hasn't seen the design doc. linking to the design might also be nice
return modernStatsPlugin; | ||
} | ||
|
||
function buildLegacyAcp(acp: WebpackPlugin): object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acp
is that intentional spelling?
const options = acp._options; | ||
const modernOptions = { ...options }; | ||
|
||
// TODO: Where shall we create this tsconfig with target=es5? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will we address the TODO in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question for reviewers: Where shall we create this tsconfig with target=es5? Schematics? On the fly if it does not exist?
…erential loading This updates a webpack configuration which has been created by a webpack-based builder for differential loading. For this, it duplicates the existing configuration and modifies e. g. the name of the bundles to generate (` [name].modern.js` instead of `[name].js`), the resolve array, and the Angular Compiler Plugin’s reference to the tsconfig.json. Because of this strategy, just one webpack config needs to be maintained per builder. The other one is retrieved from it by this logic. This is esp. important if the CLI supports several bundles in future, e. g. ES5, ES2015, ES2016, ES2017, etc. This PR is currently not used but it is the foundation for further ones. Also see: https://docs.google.com/document/d/13k84oGwrEjwPyAiAjUgaaM7YHJrzYXz7Cbt6CwRp9N4/edit?ts=5c652052#heading=h.gijrsdjw51q5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
const workspaceRoot = path.join( | ||
devkitRoot, | ||
'tests/angular_devkit/build_angular/test-differential-loading/'); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to avoid using the files from the file system directly, to test ideally always use the abstracted fs, as it would be easier to update a property in a file, write another file etc.. during a specs.
See here for an example: https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/build_webpack/src/webpack-dev-server/index_spec_large.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
modernOptions.tsConfigPath = tsConfigPath; | ||
|
||
const legacyAcp = new AngularCompilerPlugin(modernOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Has this been tested? Afaik this plugin doesn’t support multicompiler or we won’t use multi webpack compiler at all and use two separate webpack instances?
In addition a single build can have multiple AngularCompilerPlugin
when using Web Workers, which is not being handled here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It works if we adopt some methods a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm are you going to go for webpack multicompiler?
Also can you elaborate what you mean by adopt some methods a bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment @angular-devkit/build-webpack doesn’t have implementations for multi-compiler.
// TODO: Where shall we create this tsconfig with target=es5? | ||
// Schematics? On the fly if it does not exist? | ||
|
||
let tsConfigPath = modernOptions.tsConfigPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think creating an extra config, might complicate things a bit especially considering the web workers, which need a separate tsconfig, meaning that each 'build' will have multiple config files. See: #13700
Not sure if it best to change the file script target on the fly.
//cc @filipesilva what do you think?
Also this would increase maintain in tsconfig files for users.
So, if users have workers and a differential severing they end up with 4 tsconfig for their application which users would need to keep in sync if they do a change.
- tsconfig for the app es5
- tsconfig for the app es2015
- tsconfig for the worker es5
- tsconfig for the worker es2015
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH, I don't like it either. However, I see no alternative for this. Or is it possible to pass an object literal representing the contents of a tsconfig.json to the AngularCompilerPlugin? I guess, in this case the AngularCompilerPlugin also needs to write it to hard disk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can pass the compiler options to the AngularCompilerPlugin.
export interface AngularCompilerPluginOptions { |
Why should the angular compiler plugin write the file to disk?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that means I could read the tsconfig.json into an object, modify it's target in memory and assign it to the compilerOptions
property, right? In this case we don't need a seperate tsconfig.json for this target on disk. Do I see this right?
|
||
// TODO: Do we need an own polyfill file for modern browsers? If yes, where is it created? | ||
|
||
if (file.endsWith('polyfills.ts')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn’t seem right, polyfills file can be named anything. It can be foo.ts
.
Also, I believe polyfills for modern and legacy will be internal which @clydin is working on something for zone.js
const StatsPlugin = require('stats-webpack-plugin'); | ||
|
||
|
||
export function createWebpackMultiConfig(config: webpack.Configuration): webpack.Configuration[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not quite understanding how this fits in the builder. You need a webpack config here and you transform it afterwards.
Why not use the existing methods to generate two separate config files and avoid post transformations?
Example:
const webpackConfigs = (wco) => [
getCommonConfig(wco),
getBrowserConfig(wco),
getStylesConfig(wco),
getStatsConfig(wco),
];
const [legacyConfig, modernConfig] = [
generateBrowserWebpackConfigFromContext(
legacyBrowserOptions,
context,
wco => webpackConfigs(wco),
host,
),
generateBrowserWebpackConfigFromContext(
moderBrowserOptions,
context,
wco => webpackConfigs(wco),
host,
),
];
Then, based on the type of build type change the file output paths and script target, This is something similar to how the serve builder generates it's webpack config. You can also use the new transformations hooks, if you need to do post transformation. Something like https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/build_angular/src/dev-server/index.ts#L123 //@clydin knows more about this feature.
There are some helper methods for webpack here: https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts
However, I am still not sure how everything will be glued together seeing this logic. As based on the design doc I was under the impression that the browser builder will implement the differential serving logic and the differential-builder responsibility was more to orchestrate to the different browser builders.
If the browser builder will be responsible for both builds, should this code
angular-cli/packages/angular_devkit/build_angular/src/browser/index.ts
Lines 267 to 277 in 42ef582
switchMap(() => from(buildBrowserWebpackConfigFromContext(options, context, host))), | |
switchMap(({ workspace, config }) => { | |
if (configFn) { | |
return configFn(workspace, config).pipe( | |
map(config => ({ workspace, config })), | |
); | |
} else { | |
return of({ workspace, config }); | |
} | |
}), | |
switchMap(({workspace, config}) => { |
buildBrowserWebpackConfigFromContext
run twice?
return modernPlugins; | ||
} | ||
|
||
function buildModernStatsPlugin(): webpack.Plugin { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about the other profile plugins such as the chrome-profiler
and speed-measure
and also the license plugin https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/browser.ts#L64?
@@ -0,0 +1,185 @@ | |||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline comments near the implementations would definitely help the reviewers and future engineers that go through the code as they wouldn't need to jump from an implementation to another to understand why something is needed.
return modernEntry; | ||
} | ||
|
||
function buildLegacyPlugins(config: webpack.Configuration): webpack.Plugin[] | undefined { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not generate a webpack config which is already property configured for an es2015 or es5 build? Rather than having to go through certain plugins and re-create them, with a risk of skipping one and increasing maintenance, if the original webpack configurations are changed.
resolve: buildLegacyResolve(config), | ||
}; | ||
|
||
const modernConfig: webpack.Configuration = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this approach you are missing some configuration for es2015 https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts#L236 and https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts#L216
Hence, I strongly recommend that we avoid doing such transformations and let the webpack config builder return the appropriate configs as this is quite brittle
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
No description provided.