角度8降级模块的AoT编译

时间:2019-11-15 18:43:14

标签: angular webpack gulp ng-upgrade

在我的项目中,Angular项目是由gulp完成的,我需要设置一个混合的angular应用程序。 目前,我通过以下方式使用webpack进行操作: gulp运行webpack并将其捆绑包注入gulp生成的{strong>先前文件夹中。 我的webpack配置:

dist

我的gulp任务启动了webpack:

module.exports = {
    mode: 'development',
    devtool: 'source-map',
    entry: path.resolve(__dirname, './src/main/app/app.module.angular.ts'),
    output: {
        filename: 'webpack.bundle.js'
    },
    module: {
        rules: [
            { test: /\.ts?$/, use: 'ts-loader', exclude: '/node_modules/' },
            { test: /\.html?$/, use: 'raw-loader' }
        ]
    },
    resolve: { extensions: ['.ts', '.js'] },
    plugins: [
        new htmlWebpackPlugin({
            template: '.' + outputPath + 'index.html',
            inject: false // <script> reference already in file
        })
    ],
    optimization: {
        minimize: false
    }
};

我定义的角度降级模块是这样引导的:

gulp.task('main-webpack', (done) => {
    return gulp.src(path.join(paths.src, '/**/*.ts'))
        .pipe(webpackStream(require('../webpack.main.config.js'), webpack))
        .on('error', (err) => {
            gutil.log('WEBPACK ERROR', err);
        })
        .pipe(gulp.dest(gulp.paths.serve.main));
});

之后,我将@NgModule({ imports: [ BrowserModule, CommonModule, HttpClientModule, TranslateModule.forRoot() ], declarations: COMPONENTS, entryComponents: COMPONENTS, providers: [...] }) export class MainAppModule { constructor() { } ngDoBootstrap(){} // required to start hybrid app } const bootstrapFn = (extraProviders: StaticProvider[]) => { const platformRef = platformBrowserDynamic(extraProviders); return platformRef.bootstrapModule(MainAppModule); }; const MainAngularDowngradedModule = angular .module( 'app.angular', [ downgradeModule(bootstrapFn)] ); 作为对angularjs应用程序根模块的依赖项,一切正常。 但是我想通过使用AoT编译从包中删除angular编译器。 我尝试使用https://www.npmjs.com/package/@ngtools/webpack 使用以下webpack配置:

'app.angular'

当我从上述配置开始时,出现此错误:

    mode: 'production',
    devtool: false,
    entry: path.resolve(__dirname, './src/main/app/app.module.angular.ts'),
    output: { filename: 'webpack.bundle.js' },
    module: {
        rules: [
            { test: /\.ts?$/,  use: '@ngtools/webpack' },
            { test: /\.html?$/, use: 'raw-loader' }
        ]
    },
    resolve: { extensions: ['.ts', '.js'] },
    plugins: [
        new htmlWebpackPlugin({
            template: '.' + outputPath + 'index.html',
            inject: false
        }),
        new AngularCompilerPlugin({
            mainPath: './src/main/app/app.module.angular.ts',
            tsConfigPath: './tsconfig.json',
        })
    ],
    optimization:{
        minimize: false,
        noEmitOnErrors: true,
    }

组件定义中的模板引用也不适用于不同的weboack设置: jit设置要求: angular.js:13920 Error: No NgModule metadata found for 'MainAppModule'. at NgModuleResolver.resolve (https://localhost:8080/main/webpack.bundle.js:53749:23) at CompileMetadataResolver.getNgModuleMetadata (https://localhost:8080/main/webpack.bundle.js:52856:43) at JitCompiler._loadModules (https://localhost:8080/main/webpack.bundle.js:59037:51) at JitCompiler._compileModuleAndComponents (https://localhost:8080/main/webpack.bundle.js:59018:36) at JitCompiler.compileModuleAsync (https://localhost:8080/main/webpack.bundle.js:58978:37) at CompilerImpl.compileModuleAsync (https://localhost:8080/main/webpack.bundle.js:107707:31) at compileNgModuleFactory__PRE_R3__ (https://localhost:8080/main/webpack.bundle.js:27322:21) at PlatformRef.bootstrapModule (https://localhost:8080/main/webpack.bundle.js:27536:16) at app_module_angular_bootstrapFn (https://localhost:8080/main/webpack.bundle.js:110384:24) at Object.<anonymous> (https://localhost:8080/main/webpack.bundle.js:109133:26) <shop1 class="ng-scope"> 而aot适用于: template: require('./shop.component.html').default;

我该如何解决上述错误? 有没有办法让jit和aot并存而无需在每个组件中进行重大修改?

谢谢 很抱歉,问题太长时间了:)

1 个答案:

答案 0 :(得分:0)

我最终通过将应用程序模块与主模块分离,解决了这个问题,其中包含main.ts和main.aot.ts文件,这些文件仅用于设置降级的模块并导入AppModule。 main.aot.ts看起来像这样:

import 'reflect-metadata';
import * as angular from 'angular';
import { platformBrowser } from '@angular/platform-browser';
// in main.ts: import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { enableProdMode } from '@angular/core';
import { NgModule, StaticProvider, Inject } from '@angular/core';
import { downgradeModule } from '@angular/upgrade/static';

import { MainAppModuleNgFactory } from './app/app.module.angular.ngfactory';
// in main.ts: import { MainAppModule } from './app/app.module.angular';

enableProdMode(); // not present in main.ts

const bootstrapFn = (extraProviders: StaticProvider[]) => {
  const platformRef = platformBrowser(extraProviders);
  return platformRef.bootstrapModuleFactory(MainAppModuleNgFactory);
};

const MainAngularDowngradedModule = angular
  .module( 'app.angular', [ downgradeModule(bootstrapFn)] );

用于aot的webpack配置如下:

module.exports = {
    mode: 'production',
    devtool: false,
    entry: path.resolve(__dirname, './src/main/main.aot.ts'),
    output: {
        filename: 'webpack.bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.ts?$/,
                use: '@ngtools/webpack',
                exclude: [
                    /node_modules/,
                    path.resolve(__dirname, './src/main/main.ts'),
                ]
            },{
                test: /\.html?$/,
                use: 'raw-loader',
            },{
                test: /\.scss?$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            }
        ]
    },
    resolve: {
        extensions: ['.ts', '.js']
    },
    plugins: [
        new AngularCompilerPlugin({
            entryModule: path.resolve(__dirname, './src/main/main.aot.ts#MainAppModule'),
            tsConfigPath: './tsconfig.aot.json',
        }),
    ],
    optimization:{
        minimize: true,
        noEmitOnErrors: true,
    }
};

最后,gulp任务看起来像这样:

gulp.task('bundle:main-webpack', function(){
    const config = (conf.env === ENVIRONMENTS.PRODUCTION || conf.env === ENVIRONMENTS.STAGING)
          ? '../webpack.prod.config.js'
          : '../webpack.main.config.js';

    return gulp.src(paths.src + '/**/*.ts')
        .pipe(webpackStream(require(config), webpack))
        .on('error', (err) => {
            gutil.log('WEBPACK ERROR', err);
        })
        .pipe(gulp.dest(paths.dist + '/main'));
});

此设置仍有一定的优化空间,但至少不会失败:)