代码之家  ›  专栏  ›  技术社区  ›  Robby

角度5构建生成main。以MB为单位进行捆绑,这会在生产中造成性能问题

  •  0
  • Robby  · 技术社区  · 6 年前

    我在我的项目中使用angular 5,带有网页3.10。当我尝试构建应用程序时,构建的主捆绑包文件约为2.8 MB,这会在生产中产生性能问题。我正在使用“npm运行构建:prod--aot--构建优化器”来构建应用程序。我阅读了其他堆栈溢出文章以了解解决方案,并意识到我正在进行的构建不包含供应商文件。我尝试使用各种文章建议的不同方法,但都没有成功。请帮忙。作为参考,我正在上传我的网页包。配置。js,网页包。常见的js,网页包。prod.js,主。浏览器ts,多填料。ts

    webpack.config.js
    
    switch (process.env.NODE_ENV) {
      case 'prod':
      case 'production':
        module.exports = require('./config/webpack.prod')({env: 'production'});
        break;
      case 'test':
      case 'testing':
        module.exports = require('./config/webpack.test')({env: 'test'});
        break;
      case 'dev':
      case 'development':
      default:
        module.exports = require('./config/webpack.dev')({env: 'development'});
    }

    webpack.common.js
    
    const helpers = require('./helpers');
    
    /**
     * Webpack Plugins
     *
     * problem with copy-webpack-plugin
     */
    const DefinePlugin = require('webpack/lib/DefinePlugin');
    const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    const HtmlElementsPlugin = require('./html-elements-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin');
    const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
    const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin');
    const ngcWebpack = require('ngc-webpack');
    
    const buildUtils = require('./build-utils');
    
    
    /**
     * Webpack configuration
     *
     * See: http://webpack.github.io/docs/configuration.html#cli
     */
    module.exports = function (options) {
      const isProd = options.env === 'production';
      const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, options.metadata || {});
      const ngcWebpackConfig = buildUtils.ngcWebpackSetup(isProd, METADATA);
      const supportES2015 = buildUtils.supportES2015(METADATA.tsConfigPath);
    
      const entry = {
        polyfills: './src/polyfills.browser.ts',
        main:      './src/main.browser.ts'
      };
    
      Object.assign(ngcWebpackConfig.plugin, {
        tsConfigPath: METADATA.tsConfigPath,
        mainPath: entry.main
      });
    
      return {
    
        entry: entry,
    
    
        resolve: {
          mainFields: [ ...(supportES2015 ? ['es2015'] : []), 'browser', 'module', 'main' ],
    
          extensions: ['.ts', '.js', '.json'],
    
    
          modules: [helpers.root('src'), helpers.root('node_modules')],
    
    
          alias: buildUtils.rxjsAlias(supportES2015)
        },
    
    
        module: {
    
          rules: [
            ...ngcWebpackConfig.loaders,
    
    
            {
              test: /\.css$/,
              use: ['to-string-loader', 'css-loader'],
              exclude: [helpers.root('src', 'styles')]
            },
    
    
            {
              test: /\.scss$/,
              use: ['to-string-loader', 'css-loader', 'sass-loader'],
              exclude: [helpers.root('src', 'styles')]
            },
    
            {
              test: /\.html$/,
              use: 'raw-loader',
              exclude: [helpers.root('src/index.html')]
            },
    
            /**
             * File loader for supporting images, for example, in CSS files.
             */
            {
              test: /\.(jpg|png|gif)$/,
              use: 'file-loader'
            },
    
            /* File loader for supporting fonts, for example, in CSS files.
            */
            {
              test: /\.(eot|woff2?|svg|ttf)([\?]?.*)$/,
              use: 'file-loader'
            }
    
          ],
    
        },
    
        plugins: [
    
          new DefinePlugin({
            'ENV': JSON.stringify(METADATA.ENV),
            'HMR': METADATA.HMR,
            'AOT': METADATA.AOT,
            'process.env.ENV': JSON.stringify(METADATA.ENV),
            'process.env.NODE_ENV': JSON.stringify(METADATA.ENV),
            'process.env.HMR': METADATA.HMR
          }),
    
    
          new CommonsChunkPlugin({
            name: 'polyfills',
            chunks: ['polyfills']
          }),
    
          new CommonsChunkPlugin({
            minChunks: Infinity,
            name: 'inline'
          }),
          new CommonsChunkPlugin({
            name: 'main',
            async: 'common',
            children: true,
            minChunks: 2
          }),
    
    
    
          new CopyWebpackPlugin([
            { from: helpers.root('src/assets'), to: 'assets' },
            { from: helpers.root('src/assets/img'), to: 'assets/img' },
            { from: helpers.root('src/meta')},
            { from: helpers.root('node_modules/font-awesome'), to: 'font-awesome' },
            { from: helpers.root('node_modules/primeng/resources/primeng.min.css'), to: 'resources' },
            { from: helpers.root('node_modules/primeng/resources/themes/_theme.scss'), to: 'resources/themes' },
            { from: helpers.root('src/assets/css/themes/citi-prime'), to: 'resources/themes/citi-prime' }
          ],
            isProd ? { ignore: [ 'mock-data/**/*' ] } : undefined
          ),
    
          /*
          * Plugin: HtmlWebpackPlugin
          * Description: Simplifies creation of HTML files to serve your webpack bundles.
          * This is especially useful for webpack bundles that include a hash in the filename
          * which changes every compilation.
          *
          * See: https://github.com/ampedandwired/html-webpack-plugin
          */
          new HtmlWebpackPlugin({
            template: 'src/index.html',
            title: METADATA.title,
            chunksSortMode: function (a, b) {
              const entryPoints = ["inline","polyfills","sw-register","styles","vendor","main"];
              return entryPoints.indexOf(a.names[0]) - entryPoints.indexOf(b.names[0]);
            },
            metadata: METADATA,
            inject: 'body',
            xhtml: true,
            minify: isProd ? {
              caseSensitive: true,
              collapseWhitespace: true,
              keepClosingSlash: true
            } : false//,
            //baseUrl: isProd ? '.' : '/'
          }),
    
    
          new ScriptExtHtmlWebpackPlugin({
            sync: /inline|polyfills|vendor/,
            defaultAttribute: 'async',
            preload: [/polyfills|vendor|main/],
            prefetch: [/chunk/]
          }),
    
          new HtmlElementsPlugin({
            publicPath: '/',
            headTags: require('./head-config.common')
          }),
    
    
          new LoaderOptionsPlugin({}),
    
          new ngcWebpack.NgcWebpackPlugin(ngcWebpackConfig.plugin),
    
    
          new InlineManifestWebpackPlugin(),
        ],
    
    
        node: {
          global: true,
          crypto: 'empty',
          process: true,
          module: false,
          clearImmediate: false,
          setImmediate: false
        }
    
      };
    }

    wepack.prod.js
    
    
    const helpers = require('./helpers');
    const buildUtils = require('./build-utils');
    
    /**
     * Used to merge webpack configs
    */
    const webpackMerge = require('webpack-merge');
    /**
     * The settings that are common to prod and dev
    */
    const commonConfig = require('./webpack.common.js');
    
    /**
     * Webpack Plugins
     */
    const SourceMapDevToolPlugin = require('webpack/lib/SourceMapDevToolPlugin');
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const HashedModuleIdsPlugin = require('webpack/lib/HashedModuleIdsPlugin')
    const PurifyPlugin = require('@angular-devkit/build-optimizer').PurifyPlugin;
    const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    
    
    
    function getUglifyOptions (supportES2015) {
      const uglifyCompressOptions = {
        pure_getters: true, /* buildOptimizer */
        // PURE comments work best with 3 passes.
        // See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
        passes: 3         /* buildOptimizer */
      };
    
      return {
        ecma: supportES2015 ? 6 : 5,
        warnings: false,    // TODO verbose based on option?
        ie8: false,
        mangle: true,
        compress: uglifyCompressOptions,
        output: {
          ascii_only: true,
          comments: false
        }
      };
    }
    
    module.exports = function (env) {
      const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
      const supportES2015 = buildUtils.supportES2015(buildUtils.DEFAULT_METADATA.tsConfigPath);
      const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, {
        host: process.env.HOST || 'localhost',
        port: process.env.PORT || 8080,
        ENV: ENV,
        HMR: false
      });
    
    
      METADATA.envFileSuffix = METADATA.E2E ? 'e2e.prod' : 'prod';
    
      return webpackMerge(commonConfig({ env: ENV, metadata: METADATA }), {
    
    
        output: {
    
    
          path: helpers.root('dist'),
    
    
          filename: '[name].[chunkhash].bundle.js',
    
    
          sourceMapFilename: '[file].map',
    
    
          chunkFilename: '[name].[chunkhash].chunk.js'
    
        },
    
        module: {
    
          rules: [
    
    
            {
              test: /\.css$/,
              loader: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: 'css-loader'
              }),
              include: [helpers.root('src', 'styles')]
            },
    
    
            {
              test: /\.scss$/,
              loader: ExtractTextPlugin.extract({
                fallback: 'style-loader',
                use: 'css-loader!sass-loader'
              }),
              include: [helpers.root('src', 'styles')]
            },
    
          ]
    
        },
    
    
        plugins: [
    
          new SourceMapDevToolPlugin({
            filename: '[file].map[query]',
            moduleFilenameTemplate: '[resource-path]',
            fallbackModuleFilenameTemplate: '[resource-path]?[hash]',
            sourceRoot: 'webpack:///'
          }),
    
    
    
          new ExtractTextPlugin('[name].[contenthash].css'),
    
          new PurifyPlugin(), /* buildOptimizer */
    
          new HashedModuleIdsPlugin(),
          new ModuleConcatenationPlugin(),
    
    
          new UglifyJsPlugin({
            sourceMap: true,
            uglifyOptions: getUglifyOptions(supportES2015)
          }),
         
        
    
        ],
    
    
        node: {
          global: true,
          crypto: 'empty',
          process: false,
          module: false,
          clearImmediate: false,
          setImmediate: false
        }
    
      });
    }

    s

    main.browser.js
    
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    import { environment } from 'environments/environment';
    
    //import '../node_modules/font-awesome/css/font-awesome.min.css';
    //import '../node_modules/primeng/resources/themes/omega/theme.scss';
    //import '../node_modules/primeng/resources/primeng.min.css';
    
    import './styles/styles.scss'
    
    
    import { AppModule } from './app';
    
    
    export function main(): Promise<any> {
      return platformBrowserDynamic()
        .bootstrapModule(AppModule)
        .then(environment.decorateModuleRef)
        .catch((err) => console.error(err));
    }
    
    
    switch (document.readyState) {
      case 'loading':
        document.addEventListener('DOMContentLoaded', _domReadyHandler, false);
        break;
      case 'interactive':
      case 'complete':
      default:
        main();
    }
    
    function _domReadyHandler() {
     document.removeEventListener('DOMContentLoaded', _domReadyHandler, false);
     main();
    }

    polyfills.js
    
     import 'core-js/es6/symbol';
     import 'core-js/es6/object';
     import 'core-js/es6/function';
     import 'core-js/es6/parse-int';
     import 'core-js/es6/parse-float';
     import 'core-js/es6/number';
     import 'core-js/es6/math';
     import 'core-js/es6/string';
     import 'core-js/es6/date';
     import 'core-js/es6/array';
     import 'core-js/es6/regexp';
     import 'core-js/es6/map';
     import 'core-js/es6/weak-map';
     import 'core-js/es6/set';
    
    
     import 'classlist.js';  // Run `npm install --save classlist.js`.
    
    
    import 'core-js/es6/reflect';
    import 'core-js/es7/reflect';
    
    
    
     import 'web-animations-js';  // Run `npm install --save web-animations-js`.
    
    import 'zone.js/dist/zone';
    
    if ('production' === ENV) {
      // Production
    
    } else {
    
      // Development
    }
    3 回复  |  直到 6 年前
        1
  •  1
  •   LukáÅ¡ Jurygáček    6 年前

    您可以在一个大模块中声明组件/指令/模块,而不是单独声明。

    在我们的项目中,由于历史背景,我们有这个问题。然后,我们的主块包括一些其他模块,它们应该在单独的块中。这是因为结构不好。

    当然,延迟加载模块是您的朋友,因为 帕尼·库马尔 提到。

        2
  •  0
  •   user3847870    6 年前

    我看到包裹了。json的脚本为aot-“npm run build:aot:prod”。这将在编译代码时启用aot。您正在运行的命令可能未在应用程序中启用aot。 此外,只要确保AOT正常工作,就需要将所有私有变量和方法都移动到公共位置,并检查html中是否有死代码(如果它抛出错误)。 希望这能奏效。

        3
  •  0
  •   Phani Kumar    6 年前

    主要的捆js大小可以通过延迟加载来减少,延迟加载可以创建可按需加载的模块

    示例:

    import { Routes, RouterModule } from "@angular/router";
    import { ModuleWithProviders } from "@angular/core";
    
    
    
    import { AuthenticateService } from '../authenticate/authenticate.module';
    import { FacilitiesComponent } from './components/facilities.component';
    
    
    const projectsRoutes: Routes = [
    
        {
            path: '',
            component: FacilitiesComponent,
            canActivate: [AuthenticateService],
            canActivateChild: [AuthenticateService],
            children: [
                {
                    path: 'projectlist',
                    loadChildren: './projects-list/projects-list.module#ProjectsListModule'
                },
                {
                    path: 'project/:pid/docmng/:fid',
                    loadChildren: '../facilities/project-document/project.module#ProjectModule'
                }
            ]
        }
    ];
    
    
    
    export const FacilitiesRouting: ModuleWithProviders = RouterModule.forChild(projectsRoutes);
    
    
    $ npm run build
    
    > skysite-platform-client2@0.0.0 build E:\SkySite-new\skysite-platform-client
    > ng build --prod
    
    Date: 2018-05-17T12:40:26.949Z
    Hash: 0b89e566c023ac3d2fb5
    Time: 156588ms
    chunk {8} 8.3421be99f16d735369c2.chunk.js () 1.67 kB  [rendered]
    chunk {scripts} scripts.b23d003bdba35060d12d.bundle.js (scripts) 503 kB [initial] [rendered]
    chunk {0} 0.e85cc76f90b3ae5b88a6.chunk.js (common) 123 kB  [rendered]
    chunk {1} 1.31677c41f09d5a650d83.chunk.js () 2.47 MB  [rendered]
    chunk {2} 2.52380e8925d7e658149e.chunk.js () 89.9 kB  [rendered]
    chunk {3} 3.92474b63b4fbb521a866.chunk.js () 82.5 kB  [rendered]
    chunk {4} 4.0faac9190c7b1e36d1e6.chunk.js () 151 kB  [rendered]
    chunk {5} 5.f3296c5e15119655f3ce.chunk.js () 1.77 kB  [rendered]
    chunk {6} 6.eb8af258a302bd9d066e.chunk.js () 131 kB  [rendered]
    chunk {7} 7.0521fe6f5f3714081264.chunk.js () 115 kB  [rendered]
    chunk {9} 9.92a24c750caada0e26c2.chunk.js () 9.35 kB  [rendered]
    chunk {10} 10.3dd571f08fa3895c8730.chunk.js () 49 kB  [rendered]
    chunk {11} polyfills.165ea84e5245184acc68.bundle.js (polyfills) 98.2 kB [initial] [rendered]
    chunk {12} main.b02e6fabeb708e73d01f.bundle.js (main) 500 kB [initial] [rendered]
    chunk {13} styles.cdbcc00089657e555f43.bundle.css (styles) 222 kB [initial] [rendered]
    chunk {14} inline.3153333f01d40d57ce09.bundle.js (inline) 1.65 kB [entry] [rendered]