Bagaimana sebenarnya saya menerapkan aplikasi Angular 2 + Typecript + systemjs?

103

Ada tutorial quickstarter di angular.io yang menggunakan skrip & systemjs. Sekarang saya sudah menjalankan miniapp tersebut, bagaimana saya akan membuat sesuatu yang dapat diterapkan? Saya tidak dapat menemukan info apa pun tentang itu sama sekali.

Apakah saya memerlukan alat tambahan, pengaturan tambahan di System.config?

(Saya tahu bahwa saya dapat menggunakan webpack & membuat satu bundle.js, tetapi saya ingin menggunakan systemjs seperti yang digunakan dalam tutorial)

Bisakah seseorang membagikan proses pembuatannya dengan penyiapan ini (Angular 2, TypeScript, systemjs)

Brian G. Bell
sumber
Berikut resep saya untuk membuat aplikasi ng2 untuk penerapan menggunakan JSPM: stackoverflow.com/a/34616199/3532945
brando
2
jawaban sederhana membangun -prod stackoverflow.com/a/38421680/5079380
Amr ElAdawy

Jawaban:

66

Hal utama yang harus dipahami pada level ini adalah bahwa menggunakan konfigurasi berikut, Anda tidak dapat menggabungkan file JS yang dikompilasi secara langsung.

Pada konfigurasi compiler 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"
  ]
}

Di HTML

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

Faktanya, file JS ini akan berisi modul anonim. Modul anonim adalah file JS yang menggunakanSystem.register tetapi tanpa nama modul sebagai parameter pertama. Ini adalah apa yang dihasilkan kompilator skrip secara default ketika systemjs dikonfigurasi sebagai manajer modul.

Jadi agar semua modul Anda menjadi satu file JS, Anda perlu memanfaatkan outFileproperti dalam konfigurasi compiler TypeScript Anda.

Anda dapat menggunakan inside teguk untuk melakukan itu:

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

Ini dapat digabungkan dengan beberapa pemrosesan lainnya:

  • untuk memperburuk hal-hal file TypeScript yang dikompilasi
  • untuk membuat app.jsfile
  • untuk membuat vendor.jsfile untuk perpustakaan pihak ketiga
  • untuk membuat boot.js file untuk mengimpor modul yang mem-bootstrap aplikasi. File ini harus disertakan di akhir halaman (ketika semua halaman dimuat).
  • untuk memperbarui index.htmluntuk memperhitungkan kedua file ini

Dependensi berikut digunakan dalam tugas gulp:

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

Berikut ini contoh agar bisa diadaptasi.

  • Buat app.min.jsfile

    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'));
    });
  • Buat vendors.min.jsfile

    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'));
    });
  • Buat boot.min.jsfile

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

    The config.prod.jshanya berisi berikut:

     System.import('boot')
        .then(null, console.error.bind(console));
  • Perbarui index.htmlfile

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

    The index.htmlterlihat seperti berikut:

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

Perhatikan bahwa System.import('boot');harus dilakukan di akhir bagian isi untuk menunggu semua komponen aplikasi Anda didaftarkan dari app.min.jsfile.

Saya tidak menjelaskan di sini cara menangani minifikasi CSS dan HTML.

Thierry Templier
sumber
1
bisakah Anda membuat repo github dengan sebuah contoh?
jdelobel
Saya mengikuti instruksi Anda dan semua terlihat baik-baik saja sehubungan dengan menelan. Namun, ketika saya menjalankan aplikasi di browser, saya mendapatkan kesalahan log konsol ini: "system.src.js: 1625 Uncaught TypeError: Beberapa panggilan anonim System.register dalam file modul yang sama." Ada ide apa artinya ini dan bagaimana cara memperbaikinya?
AngularM
@AngularM: apakah Anda memiliki parameter outFile? Ini adalah kunci untuk kesalahan Anda ;-)
Thierry Templier
Saya memilikinya di file gulp saya dan tsconfig
AngularM
Bisakah Anda melihat proyek github yang saya kirimkan? Lihat komentar saya di atas. Apakah Anda melihat beberapa perbedaan dengan kode Anda?
Thierry Templier
28

Anda dapat menggunakan perintah build angular2-cli

ng build -prod

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

Build yang dibuat dengan flag -prod melalui ng build -prodatau ng serve -prodmemaketkan semua dependensi ke dalam satu file , dan menggunakan teknik pengocokan pohon .

Memperbarui

Jawaban ini diajukan saat angular2 berada di rc4

Saya telah mencobanya lagi di angular-cli beta21 dan angular2 ^ 2.1.0 dan berfungsi seperti yang diharapkan

Jawaban ini membutuhkan inisialisasi aplikasi dengan angular-cli yang dapat Anda gunakan

ng new myApp

Atau yang sudah ada

ng init

Perbarui 08/06/2018

Untuk sudut 6 sintaksnya berbeda.

ng build --prod --build-optimizer

Periksa dokumentasinya

Amr ElAdawy
sumber
8
Ini mengharuskan aplikasi Anda terstruktur dalam struktur beropini angular-cli.
Michael Pell
2
@Amr ElAdawy FYI angular-cli pindah ke webpack. Pertanyaan ini terkait dengan SystemJS. ng build tidak berhasil untuk saya.
Shahriar Hasan Sayeed
@ShahriarHasanSayeed Apakah Anda mengacu pada waktu saya mengirimkan jawaban atau waktu Anda mencobanya?
Amr ElAdawy
@AmrElAdawy, dapatkah Anda menambahkan versi untuk modul tempat ini benar-benar berfungsi. Angular2 telah berubah sedikit sejak Juli.
ppovoski
2
Sangat mudah untuk mengubah tutorial Tour of Heroes ke versi cli. Buat saja proyek baru menggunakan cli dan kemudian salin file tutorialnya.
Rosdi Kasim
12

Anda dapat membangun proyek Angular 2 (2.0.0-rc.1) di Typecript menggunakan SystemJS dengan Gulp dan SystemJS-Builder .

Di bawah ini adalah versi sederhana tentang cara membuat, menggabungkan, dan mengecilkan Tour of Heroes yang menjalankan 2.0.0-rc.1 ( sumber lengkap , contoh langsung ).

gulpfile.js

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var typescript = require('gulp-typescript');
var systemjsBuilder = require('systemjs-builder');

// Compile TypeScript app to JS
gulp.task('compile:ts', function () {
  return gulp
    .src([
        "src/**/*.ts",
        "typings/*.d.ts"
    ])
    .pipe(sourcemaps.init())
    .pipe(typescript({
        "module": "system",
        "moduleResolution": "node",
        "outDir": "app",
        "target": "ES5"
    }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('app'));
});

// Generate systemjs-based bundle (app/app.js)
gulp.task('bundle:app', function() {
  var builder = new systemjsBuilder('public', './system.config.js');
  return builder.buildStatic('app', 'app/app.js');
});

// Copy and bundle dependencies into one file (vendor/vendors.js)
// system.config.js can also bundled for convenience
gulp.task('bundle:vendor', function () {
    return gulp.src([
        'node_modules/jquery/dist/jquery.min.js',
        'node_modules/bootstrap/dist/js/bootstrap.min.js',
        'node_modules/es6-shim/es6-shim.min.js',
        'node_modules/es6-promise/dist/es6-promise.min.js',
        'node_modules/zone.js/dist/zone.js',
        'node_modules/reflect-metadata/Reflect.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/systemjs/dist/system.src.js',
      ])
        .pipe(concat('vendors.js'))
        .pipe(gulp.dest('vendor'));
});

// Copy dependencies loaded through SystemJS into dir from node_modules
gulp.task('copy:vendor', function () {
  gulp.src(['node_modules/rxjs/**/*'])
    .pipe(gulp.dest('public/lib/js/rxjs'));

  gulp.src(['node_modules/angular2-in-memory-web-api/**/*'])
    .pipe(gulp.dest('public/lib/js/angular2-in-memory-web-api'));
  
  return gulp.src(['node_modules/@angular/**/*'])
    .pipe(gulp.dest('public/lib/js/@angular'));
});

gulp.task('vendor', ['bundle:vendor', 'copy:vendor']);
gulp.task('app', ['compile:ts', 'bundle:app']);

// Bundle dependencies and app into one file (app.bundle.js)
gulp.task('bundle', ['vendor', 'app'], function () {
    return gulp.src([
        'app/app.js',
        'vendor/vendors.js'
        ])
    .pipe(concat('app.bundle.js'))
    .pipe(uglify())
    .pipe(gulp.dest('./app'));
});

gulp.task('default', ['bundle']);

system.config.js

var map = {
  'app':                                'app',
  'rxjs':                               'vendor/rxjs',
  'zonejs':                             'vendor/zone.js',
  'reflect-metadata':                   'vendor/reflect-metadata',
  '@angular':                           'vendor/@angular'
};

var packages = {
  'app':                                { main: 'main', defaultExtension: 'js' },
  'rxjs':                               { defaultExtension: 'js' },
  'zonejs':                             { main: 'zone', defaultExtension: 'js' },
  'reflect-metadata':                   { main: 'Reflect', defaultExtension: 'js' }
};

var packageNames = [
  '@angular/common',
  '@angular/compiler',
  '@angular/core',
  '@angular/http',
  '@angular/platform-browser',
  '@angular/platform-browser-dynamic',
  '@angular/router',
  '@angular/router-deprecated',
  '@angular/testing',
  '@angular/upgrade',
];

packageNames.forEach(function(pkgName) {
  packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

System.config({
  map: map,
  packages: packages
});

Seperti baja
sumber
2
Bisakah Anda jelaskan, bagaimana menjalankan SystemJs dan Gulp?
Jan D frozen
@JanD frozen Di lokasi yang sama dengan gulpfile Anda, Anda dapat menjalankan di gulp <taskname>mana "nama tugas" adalah nama tugas yang memanggil pembangun SystemJS, dalam contoh saya di atas bundle:app. Dalam tugas Gulp itu, Anda dapat menggunakan modul npm 'systemjs-builder' untuk menentukan konfigurasi dan file outfile Sistem Anda.
Steely
@ steely: Terima kasih! Bekerja seperti pesona. Berharap ke target default - metode uglify () hilang (atau saya kehilangan sesuatu). Bisakah Anda menjelaskan kepada saya bagian terakhir yang tidak jelas ini?
Jan D frozen
@Steely Maukah Anda memandu cara melakukannya dengan versi angular2 yang lebih baru?
micronyks
@ Steely. Dapatkah Anda memberikan tautan terakhir (di github) dari file build angular2 terbaru yang diperlukan untuk menjalankan aplikasi quickstart angular2?
micronyks
1

Ini boilerplate MEA2N saya untuk Angular 2: https://github.com/simonxca/mean2-boilerplate

Ini adalah boilerplate sederhana yang digunakan tscuntuk menyatukan berbagai hal. (Sebenarnya menggunakan grunt-ts , yang intinya hanya tscperintah.) Tidak perlu Wekpack, dll.

Apakah Anda menggunakan grunt atau tidak, idenya adalah:

  • tulis aplikasi Anda di folder bernama ts/(contoh:public/ts/ :)
  • gunakan tscuntuk mencerminkan struktur direktori ts/folder Anda ke dalam js/folder dan hanya file referensi di js/folder di index.html.

Untuk mendapatkan grunt-ts untuk bekerja (harus ada perintah yang setara untuk tsc biasa, Gulp, dll.), Anda memiliki properti di tsconfig.jsonpanggil Anda "outDir": "../js", dan referensi di Anda gruntfile.jsdengan:

grunt.initConfig({
  ts: {
    source: {tsconfig: 'app/ts/tsconfig.json'}
  },
  ...
});

Kemudian jalankan grunt ts, yang akan membawa aplikasi Anda public/ts/dan mencerminkannya public/js/.

Sana. Sangat mudah dimengerti. Bukan pendekatan terbaik, tapi pendekatan yang bagus untuk memulai.

Simonxca
sumber
1

Cara termudah yang saya temukan untuk membundel angular rc1 untuk systemJs adalah dengan menggunakan gulpdan 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);
        });
});

Seperti yang ditunjukkan dalam komentar, systemJ saat ini memiliki masalah saat menggabungkan komponen menggunakan moduleId: module.id

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

Rekomendasi saat ini (sudut 2 rc1) tampaknya menggunakan jalur eksplisit yaitu moduleId: '/app/path/'

paul
sumber
Ini tampak menjanjikan tetapi gagal ketika saya menggunakan jalur relatif ke templat eksternal di @Componentdekorator. bundle.jsmencoba untuk menyelesaikan jalur sebagai absolut meskipun mereka relatif, menyebabkan kesalahan 404 (lihat stackoverflow.com/questions/37497635/… ). Bagaimana Anda mengatasinya?
BeetleJuice
apakah Anda menyetel moduleIdke jalur relatif?
paul
Tidak yakin saya mengerti. Saya ada moduleId: module.iddi@Component
BeetleJuice
Itu memiliki kelemahan yang sama seperti meletakkan jalan penuh di bawah templateUrldan mengalahkan tujuan memiliki moduleIddi tempat pertama. Saya mencoba menggunakan jalur relatif seperti yang disarankan ( angular.io/docs/ts/latest/cookbook/… )
BeetleJuice
Anda mungkin lebih beruntung dengan menetapkan sendiri jalurnya secara eksplisit, misalnyamoduleId: '/app/components/home/'
paul
0

Di bawah situs web Angular.io, di bawah bagian Advanced / Deployment, disarankan bahwa cara paling sederhana untuk menyebarkan adalah 'menyalin lingkungan pengembangan ke server'.

  1. melalui bagian di bawah: Penerapan sesederhana mungkin. File proyek akhir ditampilkan di dalam bagian kode. Perhatikan bahwa itu sudah menyiapkan kode untuk memuat file paket npm dari web (sebagai ganti dari folder npm_modules lokal).

  2. pastikan itu berjalan di komputer lokal Anda (npm start). Kemudian di bawah folder proyek, salin semua yang ada di bawah sub-folder '/ src' ke bucket S3 yang telah Anda siapkan. Anda dapat menggunakan drag-and-drop untuk menyalin, selama proses itu, Anda mendapatkan opsi untuk memilih pengaturan izin untuk file, pastikan untuk membuatnya 'dapat dibaca' oleh 'semua orang'.

  3. di bawah tab 'Properti' keranjang, cari panel 'Hosting situs web statis', centang opsi 'Gunakan keranjang ini untuk menghosting situs web', dan tentukan 'index.html' untuk dokumen Indeks dan dokumen Kesalahan.

  4. klik pada situs web statis Endpoint, proyek Anda berjalan dengan baik!

Joseph Wu
sumber