angular - Webpack, Typescript och Angular2 med Ahead Of Time (AOT) kompilering?


Den senaste versionen av Angular2 möjliggör förkompilering (AOT), genom att använda denna kod i din app.bootstrap.ts-fil:

// 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 officiell dokumentation

Hur kan vi integrera Webpack och Typescript-loader med Angular2:s AOT-kompilator?

Det verkar som att det kanske ännu inte finns ett alternativ för att göra det, men jag ställer frågan på Stack Overflow så att när det blir tillgängligt kan svaret enkelt hittas.

UPPDATERING 12/10/16 - Jag fick det att fungera, se mitt svar nedan.

Svar #1

Jag fick det att fungera äntligen, se mitt repo Angular2 Webpack2 DotNET Starter

Det finns flera nödvändiga knep. Observera att AOT-kompilering inte stöder några require()-satser i dina Angular 2-komponenter. De måste konverteras till import-satser.

Först behöver du ha en andra tsconfig.json-fil, med speciella alternativ för AOT-kompilering. Jag betecknar detta med .aot.json-ändelse.

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

Du kommer också att behöva den exakt rätta kombinationen av versioner av Angular2. @angular/[email och @angular/[email fungerade INTE för mig, jag var tvungen att använda 2.0.0 för båda annars misslyckades ngc med att kompilera AOT-filerna. Här är vad jag använder framgångsrikt:

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

Dessutom behöver du ett par smidiga webpack-loaders, samtidigt som du tillåter webpack att titta i ./src-mappen samt mappen där dina AOT-kompilerade filer skrivs ut. (*.component.ngfactory.ts)

Den sista delen är mycket viktig! Om du inte talar om för webpack att inkludera de mapparna, kommer det inte att fungera. I detta exempel skrivs AOT-filerna ut till /aot-compiled i rotmappen.

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

För att generera dina AOT-filer behöver du ett NPM-skript för att göra det åt dig

package.json

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

Du kommer också behöva få din webpack-konfiguration att läsa AOT-versionen av app.bootstrap.ts - som är annorlunda än JIT-versionen. Jag skiljer den åt med .aot.ts-ändelsen så att webpack använder AOT i produktion (app.bootstrap.aot.ts), men i utvecklingsläge använder den JIT med webpack-dev-server (app.bootstrap.ts).

Slutligen kör du npm run compile:aot FÖRST. När dina AOT-filer har skrivits ut till disken, kör du din webpack-bygge med antingen webpack eller webpack-dev-server.

För ett fungerande exempel, se mitt repo Angular2 Webpack2 DotNET Starter. Det är integrerat med .NET Core 1.0, men för dem som inte använder .NET kan du fortfarande se hur Webpack 2 och Angular 2 är konfigurerade.

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

Jag använde denna webpack-konfiguration och jag gjorde AOT-kompilering med Angular2 lazy loading. Du kan se ett exempel på app för AOT/JIT-kompilering med Angular2 lazy load för produktionsläge och utvecklingsläge i detta git.

angular2-webpack2-aot

Relaterade artiklar