使用Webpack 4在混合Angular应用中设置AOT

时间:2018-08-31 15:17:26

标签: angular webpack angular2-aot angular-hybrid

我正在使用混合Angular应用处理性能问题。 它在3s左右自举。而且我注意到AoT没有运行(捆绑包中有JIT编译器)。 我正在使用@ ngtools / webpack loader和AngularCompilerPlugin,它们应该处理AoT,但不会。 无法弄清楚我的配置有什么问题。

版本:

角度6.1.2

Angular.js 1.7.3

Webpack 4.16.5

webpack.common.js

const webpack = require('webpack');
const helper = require('./helper');
const outputDir = helper.root('build-webpack');
const postcssPlugins = require('./postcss');
const rxPaths = require('rxjs/_esm5/path-mapping');
const entryPoints = ['inline', 'polyfills', 'sw-register', 'styles', 'vendor', 'main'];
const convertPathsToAliases = require('convert-tsconfig-paths-to-webpack-aliases').default;
const tsconfig = require(helper.root('tsconfig.json'));
const aliases = convertPathsToAliases(tsconfig);
const CircularDependencyPlugin = require('circular-dependency-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const copyWebpackOptions = [
    {
        from: helper.root('src/content/fonts'),
        to: `${outputDir}/content/fonts`
    },
    {
        from: helper.root('src/content/assets'),
        to: `${outputDir}/content/assets`
    },
    {
        from: helper.root('src/content/img'),
        to: `${outputDir}/content/img`
    },
    {
        from: helper.root('src/content/toc'),
        to: `${outputDir}/content/toc`
    }
];

module.exports = (env) => {

    const babelLoader = {
        loader: 'babel-loader',
        options: {
            // annotate for Angular.js code to be minified
            plugins: env.optimize ? [require('babel-plugin-angularjs-annotate')] : [],
            presets: [
                [
                    '@babel/preset-env',
                    {
                        shippedProposals: true,
                        sourceMaps: false,
                        targets: { browsers: ['ie >= 11'] },
                        useBuiltIns: 'usage'
                    }
                ]
            ]
        }
    };

    return {
        entry: {
            main: ['main.ts'],
            polyfills: ['polyfills.ts'],
            styles: ['less/styles.less']
        },
        mode: 'development',
        module: {
            rules: [
                {
                    test: /\.(png|jpg|jpeg|gif|woff|woff2)$/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                limit: 10000,
                                name: '[name].[hash:20].[ext]'
                            }
                        }
                    ]
                },
                {
                    test: /\.(eot|svg|ttf|woff|woff2)$/,
                    use: [
                        {
                            loader: 'file-loader',
                            options: {
                                limit: 10000,
                                name: '/content/fonts/[name].[hash:20].[ext]'
                            }
                        }
                    ]
                },
                {
                    test: /\.tpl.html/,
                    use: [
                        'ngtemplate-loader',
                        {
                            loader: 'html-loader',
                            options: { minimize: true }
                        },
                        {
                            loader: 'html-minifier-loader',
                            options: { collapseWhitespace: true }
                        }
                    ]
                },
                {
                    exclude: [
                        helper.root('src/less/styles.less')
                    ],
                    test: /\.css$/,
                    use: [
                        { loader: 'raw-loader' },
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'embedded',
                                plugins: postcssPlugins,
                                sourceMap: true
                            }
                        }
                    ]
                },
                {
                    exclude: [
                        helper.root('src/less/styles.less')
                    ],
                    test: /\.less$/,
                    use: [
                        { loader: 'raw-loader' },
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'embedded',
                                plugins: postcssPlugins,
                                sourceMap: true
                            }
                        },
                        {
                            loader: 'less-loader',
                            options: { sourceMap: true }
                        }
                    ]
                },
                {
                    include: [
                        helper.root('src/less/styles.less')
                    ],
                    test: /\.css$/,
                    use: [
                        'style-loader',
                        { loader: 'raw-loader' },
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'embedded',
                                plugins: postcssPlugins,
                                sourceMap: true
                            }
                        }
                    ]
                },
                {
                    include: [
                        helper.root('src/less/styles.less')
                    ],
                    test: /\.less$/,
                    use: [
                        'style-loader',
                        { loader: 'raw-loader' },
                        {
                            loader: 'postcss-loader',
                            options: {
                                ident: 'embedded',
                                plugins: postcssPlugins,
                                sourceMap: true
                            }
                        },
                        {
                            loader: 'less-loader',
                            options: { sourceMap: true }
                        }
                    ]
                },
                {
                    exclude: /node_modules/,
                    test: /\.ts$/,
                    use: [
                        // 'cache-loader',
                        babelLoader,
                        '@ngtools/webpack'
                    ]
                },
                {
                    exclude: /node_modules/,
                    test: /\.js$/,
                    use: [
                        // 'cache-loader',
                        babelLoader
                    ]
                }
            ]
        },
        node: {
            clearImmediate: false,
            crypto: 'empty',
            fs: 'empty',
            global: true,
            module: false,
            net: 'empty',
            process: true,
            setImmediate: false,
            tls: 'empty'
        },
        output: {
            chunkFilename: 'scripts/[id].[hash].chunk.js',
            crossOriginLoading: false,
            filename: 'scripts/[name].[hash].bundle.js',
            path: outputDir
        },
        plugins: [
            new CopyWebpackPlugin(copyWebpackOptions),
            new webpack.NoEmitOnErrorsPlugin(),
            new webpack.ProgressPlugin(),
            new CircularDependencyPlugin({
                cwd: process.cwd(),
                exclude: /(\\|\/)node_modules(\\|\/)/,
                failOnError: false,
                onDetected: false
            }),
            new HtmlWebpackPlugin({
                cache: true,
                chunks: 'all',
                chunksSortMode: (left, right) => {

                    const leftIdx = entryPoints.indexOf(left.names[0]);
                    const rightIdx = entryPoints.indexOf(right.names[0]);
                    if (leftIdx > rightIdx) {

                        return 1;

                    } else if (leftIdx < rightIdx) {

                        return -1;

                    }
                    return 0;

                },
                compile: true,
                excludeChunks: [],
                favicon: false,
                filename: 'index.html',
                hash: false,
                inject: true,
                // HTML minification
                minify: env.optimize ? {
                    collapseWhitespace: true,
                    html5: true,
                    minifyCSS: true,
                    preserveLineBreaks: false,
                    removeAttributeQuotes: true,
                    removeComments: true
                } : false,
                showErrors: true,
                template: './src/index.pug'
            }),
            new webpack.NamedModulesPlugin({}),
            new webpack.ProvidePlugin({
                $: 'jquery',
                _: 'underscore',
                jQuery: 'jquery',
                moment: 'moment',
                'window.jQuery': 'jquery'
            }),
            // Ignore moment locales (https://github.com/moment/moment/issues/4025)
            new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
        ],
        resolve: {
            alias: {
                ...rxPaths(),
                ...aliases
            },
            // note that .ts extension should be before .js
            // https://github.com/angular/angular-cli/issues/8508
            extensions: [
                '.ts',
                '.js'
            ],
            mainFields: [
                'browser',
                'module',
                'main'
            ],
            modules: [helper.root('node_modules'), helper.root('src')],
            symlinks: true
        },
        resolveLoader: {
            alias: rxPaths(),
            modules: [helper.root('node_modules')]
        },
        target: 'web'
    };

};

webpack.prod.js

const { AngularCompilerPlugin } = require('@ngtools/webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const webpackMerge = require('webpack-merge');
const commonConfig = require('./webpack.common');

const RobotstxtPlugin = require('robotstxt-webpack-plugin').default;

// load configs
console.log('loading prod config');

module.exports = (env) => {

    env = env ? env : {};

    return webpackMerge(commonConfig(env), {
        devtool: false,
        mode: 'production',
        module: {
            rules: [
                {
                    test: /\.pug$/,
                    use: [
                        'raw-loader',
                        {
                            loader: 'pug-html-loader',
                            options: { data: { gtmAccountId: '"GTM-5DR847C"' }, doctype: 'html' }
                        }
                    ]
                }

            ]
        },
        optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    cache: true,
                    parallel: true,
                    sourceMap: true,
                    uglifyOptions: {
                        output: {
                            beautify: false,
                            comments: false
                        },
                        warnings: false
                    }
                })
            ]
        },
        plugins: [
            new AngularCompilerPlugin({
                compilerOptions: {},
                hostReplacementPaths: { 'config/index.ts': 'config/prod.ts' },
                mainPath: 'main.ts',
                platform: 0,
                skipCodeGeneration: true,
                sourceMap: true,
                tsConfigPath: 'src/tsconfig.app.json'
            })
        ]
    });

};

tsconfig.app.json

{
    "extends": "../tsconfig.json",
    "compilerOptions": {
        "allowJs": true,
        "checkJs": false,
        "forceConsistentCasingInFileNames": false,
        "module": "es2015",
        "newLine": "lf",
        "noImplicitAny": true,
        "removeComments": true
    },
    "exclude": [
        "test.ts",
        "**/*.spec.ts",
        "tests/index.js",
        "**/*.spec.js"
    ]
}

main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { setAngularLib } from '@angular/upgrade/static';
import { AppModule } from '@crexi/app.module';
import { config } from '@crexi/config';
import { UrlService } from '@uirouter/core';
import angular from 'angular';

setAngularLib(angular);

if (config.production) {

    enableProdMode();

}

// We delay bootstrapping so the browser has time to render the splash screen. Doing so
// within requestAnimationFrame and setTimeout minimizes that delay.
requestAnimationFrame(() => {

    setTimeout(() => {

        platformBrowserDynamic().bootstrapModule(AppModule)
        .then((platformRef) => {

            const url: UrlService = platformRef.injector.get(UrlService);
            url.listen();
            url.sync();

        })
        .catch((err) => {

            console.log(err);

        });

    }, 0);

});

app.module.ts(摘录)

export class AppModule {

    constructor (private upgrade: UpgradeModule) {}

    ngDoBootstrap () {

        downgrades();
        this.upgrade.bootstrap(document.documentElement, ['crexi']);

    }

}

0 个答案:

没有答案