Angular CLIでJSZipを使用する
JavaScript で ZIP ファイルを動的に生成できる JSZip というライブラリがあります。とても便利なのですが Angular CLI プロジェクトで使用するとコンパイルエラーになるので、その解消方法のメモです。
前提条件
以下の環境で動作検証しています。
Angular CLI: 7.3.9 Node: 10.15.3 OS: win32 x64 Angular: 7.2.15 ... animations, common, compiler, compiler-cli, core, forms ... language-service, platform-browser, platform-browser-dynamic ... router Package Version ----------------------------------------------------------- @angular-devkit/architect 0.13.9 @angular-devkit/build-angular 0.13.9 @angular-devkit/build-optimizer 0.13.9 @angular-devkit/build-webpack 0.13.9 @angular-devkit/core 7.3.9 @angular-devkit/schematics 7.3.9 @angular/cli 7.3.9 @ngtools/webpack 7.3.9 @schematics/angular 7.3.9 @schematics/update 0.13.9 rxjs 6.3.3 typescript 3.2.4 webpack 4.29.0 ----------------------------------------------------------- jszip 3.2.1
プロジェクト準備
適当な Angular CLI のプロジェクトを作成し、 JSZip を追加でインストールします。 JSZip には TypeScript の型定義ファイルが含まれていないため、型定義ファイルも別途インストールが必要になります。
ng new angular-jszip-sample cd angular-jszip-sample npm i -P jszip @types/jszip
JSZip を使用した ZIP ファイルの作成(失敗する版)
※JSZip 自体の使い方についてここで特に触れることはしませんので、使い方を知りたい方はドキュメント等を参考にしてください。
JSZip を使用してファイルを生成するように AppComponent の中身を書き換えます。
// src/app/app.component.html <button (click)="createZip()">Create ZIP file</button>
// src/app/app.component.ts import { Component } from '@angular/core'; import * as JSZip from 'jszip'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { async createZip() { const zip = new JSZip(); zip.file('sample.json', JSON.stringify({ hoge: 'fuga' })); // ZIPファイルのblobデータ生成 const zipFile = await zip.generateAsync<'blob'>({ type: 'blob', platform: 'UNIX', compression: 'DEFLATE', compressionOptions: { level: 9 }, }); // ダウンロード処理など } }
そしてこれを実行すると落ちます。。。
ERROR in ./node_modules/jszip/lib/readable-stream-browser.js Module not found: Error: Can't resolve 'stream' in 'C:\Users\noxi\Projects\angular-jszip-sample\node_modules\jszip\lib' i 「wdm」: Failed to compile.
JSZip を使用した ZIP ファイルの作成(成功する版)
なにやら依存解決系で失敗している雰囲気があるので、端から綺麗に実行するのを諦めて JSZip を window 下に読み込んで使うことで解決できます。
// angular.json ... "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "src/styles.css" ], "scripts": [ "node_modules/jszip/dist/jszip.min.js" ], "es5BrowserSupport": true ...
// src/app/app.component.ts import { Component } from '@angular/core'; import * as JSZip from 'jszip'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { async createZip() { // windowから参照する様に変更した // 型定義自体は利用したいため左辺で指定する const zip: JSZip = new (window as any).JSZip(); zip.file('sample.json', JSON.stringify({ hoge: 'fuga' })); // ZIPファイルのblobデータ生成 const zipFile = await zip.generateAsync<'blob'>({ type: 'blob', platform: 'UNIX', compression: 'DEFLATE', compressionOptions: { level: 9 }, }); // ダウンロード処理など } }