Angular 12から、Webpackが5になりました。
そのせいではないと思うのですが、ビルド時にいくつかエラーになりました。
これはその対処メモです。
環境
- Angular 12.0.4
- pdfjs 2.7.570
- pdfAnnotate 1.0.14
- Node 14.17.0
Warning: Module not found: Error: Can't resolve 'crypto'
起こったこと
ng serve
時にこのようなメッセージが出力されました。
./node_modules/crypto-js/core.js:43:22-39 - Warning: Module not found: Error: Can't resolve 'crypto' in '~/node_modules/crypto-js'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
解決策
crypto-browserifyパッケージをインストールし、tsconfig.json
ファイルを編集しました。
npm i crypto-browserify
{
"compilerOptions": {
...
+ "paths": {
+ "crypto": ["./node_modules/crypto-browserify"]
Warning: Module not found: Error: Can't resolve 'stream'
起こったこと
先のcrypto
と同内容なので省略します。
解決策
stream-browserifyパッケージをインストールし、tsconfig.json
ファイルを編集しました。
npm i stream-browserify
{
"compilerOptions": {
...
+ "paths": {
+ "stream": ["./node_modules/stream-browserify"]
Warning: CommonJS or AMD dependencies can cause optimization bailouts.
起こったこと
ng serve
時にこのようなメッセージが出力されました。
Warning: ~/src/app/app.component.ts depends on 'annotpdf'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
解決策(?)
https://angular.io/guide/build#configuring-commonjs-dependencies によると、CommonJSモジュールを使うのは避けたほうがよいそうですが、使う場合は angular.json
ファイルを編集します。
"projects": {
"project-name": {
...
"architect": {
"build": {
...
"options": {
+ "allowedCommonJsDependencies": [
+ "annotpdf"
+ ]
Error: Module not found: Error: Can't resolve 'fs'
起こったこと
ng serve
時にこのようなメッセージが出力されました。
./node_modules/annotpdf/lib/annotation.js:121:25-38 - Error: Module not found: Error: Can't resolve 'fs' in '~/node_modules/annotpdf/lib'
解決(しなかった)策
package.json
ファイルを編集しました。
+ "browser": {
+ "fs": false
+ }
これでよいと聞いたんですけれど、解決しないです。
なんででしょ?
Webpackに設定追加すればよいらしい(?)
検索すると、Webpackの設定に下記を加えれば解決する(?)という話がありました。
resolve: {
fallback: {
fs: false,
},
},
Webpackは、@angular-devkit/build-angularのこのあたりで実行しているようです。
Webpackの設定箇所を探してみると、このへんで下記の呼び出し結果をまとめている様子です。
- getCommonConfig
- getBrowserConfig
- getStylesConfig
- getStatsConfig
- getAnalyticsConfig
- getCompilerConfig
- getTypeScriptConfig
上記をまとめた結果はこんなんです。
resolve: {
roots: [projectRoot],
extensions: ['.ts', '.tsx', '.mjs', '.js'],
symlinks: !buildOptions.preserveSymlinks,
modules: [wco.tsConfig.options.baseUrl || projectRoot, 'node_modules'],
mainFields: ['es2015', 'browser', 'module', 'main'],
},
fallback
を差し込む余地はなさそうです。
@angular-devkit/build-webpackを使えばよいのですが、自前でWebpackの設定を用意するのはしんどそう。。。
エラー出力箇所を追ってみる
よくわからないので、ソースを追ってみます。
エラーメッセージを出力しているのは、WebpackのCompilation.jsのようです。
出力しているModuleNotFoundError
に渡る**Can't resolve 'fs'**は、resolveMatchedConfigsかな。
参照リゾルバが解決できないとエラーになる様子です。
参照リゾルバは、ResolverFactoryが作っていました。実際にはenhanced-resolveに下請けさせてます。
enhanced-resolveのドキュメントによるとNode.jsの解決ルールに従って、解決してくれるそうです。fsはコアモジュールなので、そのままスルーっぽいですね。
解決策
@angular-builders/custom-webpackというよいものがありました。これを使うと、Angularデフォルトのwebpack設定を上書きできるようです。
インストールします。
npm i -D @angular-builders/custom-webpack
angular.json
を書き換えます。
"architect": {
"build": {
- "builder": "@angular-devkit/build-angular:browser",
+ "builder": "@angular-builders/custom-webpack:browser",
"options": {
+ "customWebpackConfig": {
+ "path": "webpack.config.ts"
+ },
"serve": {
- "builder": "@angular-devkit/build-angular:dev-server",
+ "builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "ex-pdf-annotate:build"
},
webpack.config.ts
ファイルを新規作成します。
import { Configuration } from 'webpack';
export default {
resolve: {
fallback: {
fs: false,
},
},
} as Configuration;
これでng build
とng serve
がエラーなくできるようになりました。