0%

angular-build-process

Angular的编译过程是怎样的?
通常我么使用ng build命令来编译Angular项目,但是这个命令背后的逻辑是怎样的呢?

  • ng build命令底层是用WebPack还是ESBuild
  • ng build命令是如何处理TypeScript文件的?
  • ng build命令是如何处理HTML文件的?

ts/js编译

Webpack的配置文件在这里:packages/angular_devkit/build_angular/src/tools/webpack/configs/common.ts

这个文件里我们可以看到如下rule配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
test: /\.[cm]?[tj]sx?$/,
// The below is needed due to a bug in `@babel/runtime`. See: https://github.com/babel/babel/issues/12824
resolve: { fullySpecified: false },
exclude: [
/[\\/]node_modules[/\\](?:core-js|@babel|tslib|web-animations-js|web-streams-polyfill|whatwg-url)[/\\]/,
],
use: [
{
loader: require.resolve('../../babel/webpack-loader'),
options: {
cacheDirectory: (cache.enabled && path.join(cache.path, 'babel-webpack')) || false,
aot: buildOptions.aot,
optimize: buildOptions.buildOptimizer,
supportedBrowsers: buildOptions.supportedBrowsers,
instrumentCode: codeCoverage
? {
includedBasePath: sourceRoot ?? projectRoot,
excludedPaths: getInstrumentationExcludedPaths(root, codeCoverageExclude),
}
: undefined,
} as AngularBabelLoaderOptions,
},
],
},

可以看到这个正则表达式匹配的是:

  • .ts.tsx
  • .js.jsx
  • .cjs.mjs

这些文件都会被require.resolve('../../babel/webpack-loader')这个loader处理。而这个loader的代码在这里:packages/angular_devkit/build_angular/src/tools/babel/webpack-loader.ts

这个文件里面又调用了babelLoader。所以可知,ng build命令底层是用Babel来处理TypeScript文件的。

这里可以画一个流程图:ng build -> Webpack -> Babel -> TypeScript

scss/sass/less/css编译

Webpack通过各种loader来处理不同类型的文件,比如css-loadersass-loaderless-loader等。那么什么是loader呢?loader是一个转换器,负责把一种文件格式转换为另一种文件格式。

1
output_format = loader(input_format)

loader是可以链式调用的,上一个loader的输出可以作为下一个loader的输入,比如scss文件可以先经过sass-loader处理,然后再经过css-loader处理,最后再经过style-loader处理。

1
output_format = style-loader(css-loader(sass-loader(input_format)))

Angular默认采用scss作为样式文件的扩展名,所以我们可以看到scss文件是如何被处理的:Webpack中关于样式文件的配置在这里:packages/angular_devkit/build_angular/src/tools/webpack/configs/styles.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
extensions: ['scss'],
use: [
{
loader: require.resolve('resolve-url-loader'),
options: {
sourceMap: cssSourceMap,
},
},
{
loader: require.resolve('sass-loader'),
options: getSassLoaderOptions(
root,
sassImplementation,
includePaths,
false,
!!buildOptions.verbose,
!!buildOptions.preserveSymlinks,
),
},
],
},

html编译