Como faço para realmente implantar um aplicativo system_1 do Angular 2+Typescript+?




systemjs (5)

A maneira mais fácil que encontrei de agrupar rc1 angular para systemJs é usar gulp e systemjs-builder :

gulp.task('bundle', function () {
    var path = require('path');
    var Builder = require('systemjs-builder');

    var builder = new Builder('/node_modules');

    return builder.bundle([
        '@angular/**/*.js'
        ], 
        'wwwroot/bundle.js', 
        { minify: false, sourceMaps: false })
        .then(function () {
            console.log('Build complete');
        })
        .catch(function (err) {
            console.log('Build error');
            console.log(err);
        });
});

Como apontado nos comentários, o systemJs atualmente tem problemas ao empacotar componentes usando moduleId: module.id

https://github.com/angular/angular/issues/6131

A recomendação atual (angular 2 rc1) parece ser usar caminhos explícitos, por exemplo moduleId: '/app/path/'

Há um tutorial de iniciação rápida no angular.io que usa typescript e systemjs. Agora que eu tenho esse miniapp funcionando, como eu poderia criar algo implantável? Eu não consegui encontrar nenhuma informação sobre isso.

Preciso de ferramentas extras, configurações adicionais no System.config?

(Eu sei que eu poderia usar o Webpack e criar um único bundle.js, mas eu gostaria de usar o systemjs como ele é usado no tutorial)

Alguém poderia compartilhar seu processo de compilação com essa configuração (Angular 2, TypeScript, systemjs)


A principal coisa para entender neste nível é que usando a seguinte configuração, você não pode concatir arquivos JS compilados diretamente.

Na configuração do compilador TypeScript:

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "declaration": false,
    "stripInternal": true,
    "module": "system",
    "moduleResolution": "node",
    "noEmitOnError": false,
    "rootDir": ".",
    "inlineSourceMap": true,
    "inlineSources": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}

No HTML

System.config({
  packages: {
    app: {
      defaultExtension: 'js',
      format: 'register'
    }
  }
});

De fato, esses arquivos JS conterão módulos anônimos. Um módulo anônimo é um arquivo JS que usa o System.register mas sem o nome do módulo como primeiro parâmetro. É o que o compilador typescript gera por padrão quando o systemjs é configurado como gerenciador de módulos.

Portanto, para ter todos os seus módulos em um único arquivo JS, você precisa aproveitar a propriedade outFile na sua configuração de compilador do TypeScript.

Você pode usar o seguinte dentro de gole para fazer isso:

const gulp = require('gulp');
const ts = require('gulp-typescript');

var tsProject = ts.createProject('tsconfig.json', {
  typescript: require('typescript'),
  outFile: 'app.js'
});

gulp.task('tscompile', function () {
  var tsResult = gulp.src('./app/**/*.ts')
                     .pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('./dist'));
});

Isso pode ser combinado com algum outro processamento:

  • para uglify coisas os arquivos compilados TypeScript
  • para criar um arquivo app.js
  • criar um arquivo vendor.js para bibliotecas de terceiros
  • para criar um arquivo boot.js para importar o módulo que inicializa o aplicativo. Este arquivo deve ser incluído no final da página (quando toda a página é carregada).
  • para atualizar o index.html para levar em conta esses dois arquivos

As seguintes dependências são usadas nas tarefas de gulp:

  • gole-concat
  • gulp-html-replace
  • gulp-typescript
  • gulp-uglify

O seguinte é uma amostra para que possa ser adaptada.

  • Crie o arquivo app.min.js

    gulp.task('app-bundle', function () {
      var tsProject = ts.createProject('tsconfig.json', {
        typescript: require('typescript'),
        outFile: 'app.js'
      });
    
      var tsResult = gulp.src('app/**/*.ts')
                       .pipe(ts(tsProject));
    
      return tsResult.js.pipe(concat('app.min.js'))
                    .pipe(uglify())
                    .pipe(gulp.dest('./dist'));
    });
  • Crie o arquivo vendors.min.js

    gulp.task('vendor-bundle', function() {
      gulp.src([
        'node_modules/es6-shim/es6-shim.min.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/angular2/bundles/angular2-polyfills.js',
        'node_modules/systemjs/dist/system.src.js',
        'node_modules/rxjs/bundles/Rx.js',
        'node_modules/angular2/bundles/angular2.dev.js',
        'node_modules/angular2/bundles/http.dev.js'
      ])
      .pipe(concat('vendors.min.js'))
      .pipe(uglify())
      .pipe(gulp.dest('./dist'));
    });
  • Crie o arquivo boot.min.js

    gulp.task('boot-bundle', function() {
      gulp.src('config.prod.js')
        .pipe(concat('boot.min.js'))
        .pipe(uglify())
        .pipe(gulp.dest('./dist'));
     });

    O config.prod.js contém simplesmente o seguinte:

     System.import('boot')
        .then(null, console.error.bind(console));
  • Atualize o arquivo index.html

    gulp.task('html', function() {
      gulp.src('index.html')
        .pipe(htmlreplace({
          'vendor': 'vendors.min.js',
          'app': 'app.min.js',
          'boot': 'boot.min.js'
        }))
        .pipe(gulp.dest('dist'));
    });

    O index.html parece com o seguinte:

    <html>
      <head>
        <!-- Some CSS -->
    
        <!-- build:vendor -->
        <script src="node_modules/es6-shim/es6-shim.min.js"></script>
        <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
        <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
        <script src="node_modules/systemjs/dist/system.src.js"></script>
        <script src="node_modules/rxjs/bundles/Rx.js"></script>
        <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
        <script src="node_modules/angular2/bundles/http.dev.js"></script>
        <!-- endbuild -->
    
        <!-- build:app -->
        <script src="config.js"></script>
        <!-- endbuild -->
      </head>
    
      <body>
        <my-app>Loading...</my-app>
    
        <!-- build:boot -->
        <!-- endbuild -->
      </body>
    </html>

Observe que o System.import('boot'); deve ser feito no final do corpo para aguardar que todos os componentes do aplicativo sejam registrados a partir do arquivo app.min.js

Eu não descrevo aqui a maneira de lidar com a minificação de CSS e HTML.



No site Angular.io, na seção Advanced / Deployment, é recomendável que a maneira mais simples de implantar seja "copiar o ambiente de desenvolvimento para o servidor".

  1. percorra a seção em: Implementação mais simples possível. Os arquivos finais do projeto são mostrados dentro da seção de código. Observe que ele já configura o código para carregar os arquivos do pacote npm da Web (em vez da pasta local npm_modules).

  2. verifique se ele está sendo executado em seu computador local (npm start). Em seguida, sob a pasta do projeto, copie tudo sob a subpasta '/ src' para o bucket S3 que você configurou. Você pode usar arrastar e soltar para copiar, durante esse processo, você tem a opção de selecionar a configuração de permissão para os arquivos, certifique-se de torná-los "legíveis" para "todos".

  3. na guia "Propriedades" do compartimento, procure o painel "Local de hospedagem do site estático", marque a opção "Usar este intervalo para hospedar o site" e especifique "index.html" para documento de índice e documento de erro.

  4. clique no ponto final do site estático, o seu projeto estará funcionando!


Você pode usar o comando angular2-cli build

ng build -prod

https://github.com/angular/angular-cli/wiki/build#bundling

Construções criadas com o sinalizador -prod via ng build -prod ou ng serve -prod todas as dependências em um único arquivo e fazem uso de técnicas de agitar as árvores .

Atualizar

Esta resposta foi enviada quando angular2 estava em rc4

Eu tentei novamente em angular-cli beta21 e angular2 ^ 2.1.0 e está funcionando como esperado

Essa resposta requer inicializar o aplicativo com o angular-cli que você pode usar

ng new myApp

Ou em um já existente

ng init

Atualização 08/06/2018

Para angular 6, a sintaxe é diferente.

ng build --prod --build-optimizer

Verifique a documentation





systemjs