【问题标题】:Webpack, Typescript and Angular2 with Ahead Of Time (AOT) compilation?使用 Ahead Of Time (AOT) 编译的 Webpack、Typescript 和 Angular2?
【发布时间】:2017-02-14 12:58:45
【问题描述】:

最新版本的 Angular2 允许提前 (AOT) 编译,在您的 app.bootstrap.ts 文件中使用此代码:

// The browser platform without a compiler
import { platformBrowser } from '@angular/platform-browser';

// The app module factory produced by the static offline compiler
import { AppModuleNgFactory } from './app.module.ngfactory';

// Launch with the app module factory.
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

Angular2 Official Documentation

我们如何将 Webpack 和 Typescript 加载器与 Angular2 的 AOT 编译器集成?

似乎还没有这样做的选项,但我问的是堆栈溢出问题,所以当它可用时,很容易找到答案。

2016 年 10 月 12 日更新 - 我得到了它的工作,请参阅下面的答案。

【问题讨论】:

标签: angular typescript webpack angular-cli aot


【解决方案1】:

我终于搞定了,看看我的 repo Angular2 Webpack2 DotNET Starter

有几个技巧是必要的。请注意,AOT 编译不支持 Angular 2 组件中的任何 require() 语句。它们需要转换为import 语句。

首先,您需要有第二个 tsconfig.json 文件,其中包含用于 AOT 编译的特殊选项。我用.aot.json 扩展名指定它。

tsconfig.aot.json:

{
   "compilerOptions": {
      "target": "es5",
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "allowSyntheticDefaultImports": false,
      "noEmitHelpers": true,
      "pretty": true,
      "strictNullChecks": false,
      "baseUrl": ".",
      "sourceMap": true,
      "sourceRoot": ".",
      "lib": [
         "es6",
         "dom"
      ],
      "types": [
         "lodash",
         "hammerjs",
         "jasmine",
         "node",
         "selenium-webdriver",
         "source-map",
         "uglify-js",
         "webpack",
         "materialize-css",
         "jquery",
         "kendo-ui"
      ],
      "typeRoots": [
         "./node_modules/@types"
      ],
      "outDir": "./compiled/src"
   },
   "exclude": [
      "./node_modules",
      "./**/*.e2e.ts",
      "./**/*.spec.ts",
   ],
   "awesomeTypescriptLoaderOptions": {
      "useWebpackText": true,
      "forkChecker": true,
      "useCache": true
   },
   "compileOnSave": false,
   "buildOnSave": false,
   "atom": {
      "rewriteTsconfig": false
   },
   "angularCompilerOptions": {
      "genDir": "./compiled/aot",
      "debug": true
   }
}

您还需要正确的 Angular2 版本组合。 @angular/core@2.0.2 和 @angular/common@2.0.2 对我不起作用,我不得不同时使用 2.0.0 或 ngc 无法编译 AOT 文件。这是我成功使用的:

package.json:

  "dependencies": {
    "@angular/core": "2.0.0",
    "@angular/common": "2.0.0",
    "@angular/compiler": "2.0.0",
    "@angular/compiler-cli": "0.6.2",
    "@angular/forms": "^2.0.1",
    "@angular/http": "2.0.0",
    "@angular/platform-browser": "2.0.0",
    "@angular/platform-browser-dynamic": "2.0.0",
    "@angular/platform-server": "2.0.0",
    "@angular/router": "3.0.0",
    "@angular/tsc-wrapped": "0.3.0"
}

此外,您还需要几个漂亮的 webpack 加载器,同时还允许 webpack 查看 ./src 文件夹以及您的 AOT 编译文件输出到的文件夹。 (*.component.ngfactory.ts)

最后一部分非常重要!如果你不告诉 webpack 包含这些文件夹,它就不会工作。本例中,AOT 文件输出到根目录下的/aot-compiled。

webpack.common.js

  loaders: [
     {
        test: /\.ts$/,
        include: [helpers.paths.appRoot, helpers.root('./compiled/aot')],
        exclude: [/\.(spec|e2e)\.ts$/],
        loaders: [
           '@angularclass/hmr-loader',
           'awesome-typescript-loader',
           'angular2-template-loader',
           'angular2-router-loader?loader=system',
           "angular2-load-children-loader" // this loader replaces loadChildren value to work with AOT/JIT
        ],
     },
  ]

要生成您的 AOT 文件,您需要一个 NPM 脚本来为您执行此操作

package.json

   "scripts": {
      "compile:aot": "./node_modules/.bin/ngc -p ./tsconfig.aot.json",
   }

您还需要让您的 webpack 配置读取 app.bootstrap.ts 的 AOT 版本 - 这与 JIT 版本不同。我用.aot.ts 扩展来区分它,因此在生产中,webpack 使用 AOT (app.bootstrap.aot.ts),但在开发模式下,它使用带有 webpack-dev-server (app.bootstrap.ts) 的 JIT。

最后,你运行npm run compile:aot FIRST。 将 AOT 文件输出到磁盘后,您可以使用 webpack 或 webpack-dev-server 运行 webpack 构建。

有关工作示例,请参阅我的 repo Angular2 Webpack2 DotNET Starter。它与 .NET Core 1.0 集成,但对于不使用 .NET 的用户,您仍然可以看到 Webpack 2 和 Angular 2 是如何配置的。

【讨论】:

  • 快速提示:在 package.json 脚本中无需指定 ./node_modules/.bin/ 路径,因此以下内容就足够了:"compile:aot": "ngc -p ./tsconfig.aot.json",
  • 谢谢,在某些情况下确实如此。但是,如果我从另一个 npm run 脚本链中调用 compile:aot 脚本,那么它会说“不知道 ngc 是什么”,所以我必须告诉它。但在这个纯粹的例子中,你是对的:-)
【解决方案2】:

tsconfig.json

    {
      "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "lib": ["es2015", "dom"],
        "noImplicitAny": true,
        "suppressImplicitAnyIndexErrors": true,
        "typeRoots": [
          "./node_modules/@types/"
        ]
      },
      "angularCompilerOptions": {
        "genDir": "aot",
        "skipMetadataEmit" : true
      }
    }

config/webpack-aot.config.js

/**
 * webpack2 config file for ng2 AOT compile
 * location : config/webpack.aot.js
 */
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');

const ngToolsWebpack = require('@ngtools/webpack');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
console.log(helpers.root('src', 'app', 'app.module#AppModule'));
module.exports = {
  devtool: 'source-map',
  entry: {
    'polyfills': './src/polyfills.ts',
    'app': './src/main.ts'
  },
  resolve: {
    extensions: ['*', '.ts', '.js']
  },
  output: {
    path: helpers.root('dist'),
    publicPath: '/',
    filename: '[name].[hash].js',
    chunkFilename: '[id].[hash].chunk.js'
  },

  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: '@ngtools/webpack'
      },
      {
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        include: helpers.root('public', 'images'),
        loader: 'file-loader',
        options: {
          //name: '/assets/[name].[hash].[ext]'  <-file-loaderError
          name: 'assets/[name].[ext]'
        }
      },
      {
        test: /\.css$/,
        exclude: helpers.root('src', 'app'),
        loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader' })
      },
      {
        test: /\.css$/,
        include: helpers.root('src', 'app'),
        loader: 'raw-loader'
      },
      {
        test: /\.scss$/,
        exclude: /node_modules/,
        loaders: ['raw-loader', 'sass-loader']
      },
      {
        test: /\.sass$/,
        exclude: /node_modules/,
        loaders: ['raw-loader', 'sass-loader']
      }
    ]
  },

  plugins: [
    // If you want to use jquery in ng2 uncomment this
    /*
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    }),*/
    new ngToolsWebpack.AotPlugin({
      tsConfigPath: helpers.root('tsconfig-aot.json'),
      basePath: helpers.root(''),
      entryModule: helpers.root('src', 'app', 'app.module#AppModule'),
      mainPath: helpers.root('src', 'main.ts')
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: ['app', 'polyfills']
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      options: {
        htmlLoader: {
          minimize: false
        }
      }
    }),
    new HtmlWebpackPlugin({
      template: 'public/index.html'
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
          warnings: false,
          drop_console: true
      },
      output: {
          comments: false
      }
    }),
    new ExtractTextPlugin('[name].[hash].css'),
    new webpack.DefinePlugin({
      'process.env': {
        'ENV': JSON.stringify(ENV)
      }
    })
  ]
};

我使用了这个 webpack 配置,并使用 angular2 延迟加载进行了 AOT 编译。 您可以在此 git 中查看使用 angular2 延迟加载的生产模式和开发模式的 AOT / JIT 编译示例应用程序。

angular2-webpack2-aot

【讨论】:

  • 我有点困惑@MiraGe,在你的 tsconfig-aot.json 文件中,配置 "genDir": "aot" 会生成一个包含已编译文件的 aot 文件夹,但是以后如何使用该文件夹?因为如果你运行 npm run build:aot 似乎它只是在 dist 文件夹中构建一个新的发行版,对吧?生成该 aot 文件夹究竟有什么意义?
  • 你是对的。使用@ngtools/webpack,“getDir”:“aot”是没用的。 @ngtools/webpack 将在内存中自动生成 aot 文件并自动替换 app.module#AppModule。我必须修复它:)
  • 那么tsconfig-aot.json文件上唯一必要的配置就是"target": "es5", "module": "es2015"部分?
  • 是的。仅当您使用 @ngtools/webpack 时。
  • @MiraGe 我不完全确定您的示例实际上是在调用 AOT 构建,至少在今天的 main.ts 中:仍在使用 platformBrowserDynamic().bootstrapModule(AppModule),而应该使用 platformBrowser().bootstrapModuleFactory(AppModuleNgFactory)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 2018-10-29
  • 1970-01-01
  • 2017-01-13
  • 2017-05-03
  • 2023-03-18
  • 1970-01-01
相关资源
最近更新 更多