Webpack, Typescript и Angular2 с компиляцией Ahead Of Time (AOT)?

Последняя версия Angular2 позволяет компилировать Ahead of time (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 Официальная документация

Как мы можем интегрировать загрузчики Webpack и Typescript с Angular2 компилятором AOT?

Кажется, что еще нет возможности сделать это, но я задаю вопрос о переполнении стека, поэтому, когда он доступен, ответ можно легко найти.

ОБНОВЛЕНИЕ 10/12/16. Я получил его, см. мой ответ ниже.

Ответы

Ответ 1

Я наконец-то работал, вижу свое репо Angular2 Webpack2 DotNET Starter

Существует несколько трюков. Обратите внимание, что компиляция AOT не поддерживает никаких операторов require() в ваших компонентах Angular 2. Они должны быть преобразованы в выражения 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/[email protected] и @angular/[email protected] НЕ работали для меня, мне пришлось использовать 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"
}

Кроме того, вам понадобятся несколько отличных загрузчиков веб-пакетов, а также возможность просмотра веб-страницы в папке ./src, а также для папки, на которую выводятся ваши скомпилированные файлы AOT. (*.component.ngfactory.ts)

Эта последняя часть очень важна! Если вы не сообщите веб-папке о включении этих папок, это не сработает. В этом примере файлы 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 script, чтобы сделать это для вас

package.json

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

Вам также нужно будет настроить конфигурацию вашего веб-пакета версии AOT app.bootstrap.ts, которая отличается от версии JIT. Я различаю его с расширением .aot.ts, так что в процессе производства webpack использует AOT (app.bootstrap.aot.ts), но в режиме dev он использует JIT с webpack-dev-server (app.bootstrap.ts).

Наконец, вы запустите npm run compile:aot FIRST. Когда ваши файлы AOT выводятся на диск, вы запускаете свою сборку webpack с помощью webpack или webpack-dev-server.

Для рабочего примера см. мое репо Angular2 Webpack2 DotNET Starter. Он интегрирован с .NET Core 1.0, но для тех, кто не использует .NET, вы все равно можете видеть, как настроены Webpack 2 и Angular 2.

Ответ 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
      }
    }

конфигурации /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, и я сделал компиляцию AOT с angular2 ленивой загрузкой. Вы можете увидеть пример приложения для компиляции AOT/JIT с angular2 ленивой загрузкой для производственного режима и режима dev в этом git.

angular2-webpack2-aot