wake-up-neo.com

Webpack, TypeScript und Angular2 mit AOT (AOT) -Kompilierung?

Die neueste Version von Angular2 ermöglicht die Kompilierung von AOT (Ahead of Time) mit diesem Code in Ihrer Datei 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 Offizielle Dokumentation

Wie können Webpack- und TypeScript-Loader mit dem AOT-Compiler von Angular2 integriert werden?

Es scheint, dass es möglicherweise noch keine Option dafür gibt, aber ich stelle die Frage zum Stack-Überlauf, damit die Antwort leicht gefunden werden kann, wenn sie verfügbar ist.

UPDATE 10/12/16 - Ich habe es funktioniert, siehe meine Antwort unten.

16
TetraDev

Ich habe es endlich funktioniert, siehe mein Repo Angular2 Webpack2 DotNET Starter

Es sind mehrere Tricks notwendig. Beachten Sie, dass die AOT-Kompilierung keine require()-Anweisungen in Ihren Angular 2-Komponenten unterstützt. Sie müssen in import-Anweisungen konvertiert werden.

Zunächst benötigen Sie eine zweite tsconfig.json-Datei mit speziellen Optionen für die AOT-Kompilierung. Ich bezeichne dies mit der Erweiterung .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
   }
}

Sie benötigen auch die genau richtige Kombination von Angular2-Versionen. @angular/[email protected] und @angular/[email protected] funktionierten NICHT für mich, ich musste 2.0.0 für beide verwenden oder ngc konnte die AOT-Dateien nicht kompilieren. Hier verwende ich erfolgreich:

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"
}

Darüber hinaus benötigen Sie ein paar nette Webpack-Ladeprogramme. Außerdem können Webpacks im Ordner ./src sowie in dem Ordner angezeigt werden, in den Ihre mit AOT kompilierten Dateien ausgegeben werden. (*.component.ngfactory.ts

Dieser letzte Teil ist sehr wichtig! Wenn Sie nicht angeben, dass Webpack diese Ordner einschließen soll, funktioniert es nicht. In diesem Beispiel werden die AOT-Dateien an /aot-compiled im Stammordner ausgegeben.

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
        ],
     },
  ]

Um Ihre AOT-Dateien zu erstellen, benötigen Sie ein NPM-Skript

package.json

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

Sie müssen außerdem Ihre Webpack-Konfiguration so einrichten, dass sie die AOT-Version von app.bootstrap.ts liest. Diese unterscheidet sich von der JIT-Version. Ich unterscheide es mit der Erweiterung .aot.ts, so dass Webpack in der Produktion AOT (app.bootstrap.aot.ts) verwendet, im Dev-Modus jedoch JIT mit webpack-dev-server (app.bootstrap.ts).

Schließlich führen Sie npm run compile:aot FIRST ..__ aus. Sobald Ihre AOT-Dateien auf die Festplatte ausgegeben werden, führen Sie den Webpack-Build entweder mit webpack oder webpack-dev-server aus.

Ein Arbeitsbeispiel finden Sie in meinem Repo Angular2 Webpack2 DotNET Starter . Es ist in .NET Core 1.0 integriert, aber für diejenigen, die .NET nicht verwenden, können Sie immer noch sehen, wie Webpack 2 und Angular 2 konfiguriert sind.

8
TetraDev

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)
      }
    })
  ]
};

Ich habe diese Webpack-Konfiguration verwendet und AOT mit Winkle2 Lazy Loading kompiliert. Sie können die Beispiel-App für AOT/JIT mit Winkle2 Lazy Load für den Produktionsmodus und den Dev-Modus in diesem Git sehen.

angle2-webpack2-aot

1
MiraGe