I want to use a library in Angular. (The npm package is cubing for reference). This library can run both in the browser or in node and has some specific code to both. I want it to run in the browser, but Angular compilation doesn't work because it can't find worker_threads
. I asked the library owner and he said the intended solution is to tell your build system that this import should be ignored because it's only relevant for the node variant of the code.
But I can't figure out how to tell Angular this. How do I tell it: Please ignore this import in this node module, we're never going to reach the code that uses it?
Error: Can't resolve 'worker_threads' in REDACTED/node_modules/cubing/dist/esm
If that's not possible, I guess I could consider doing a node_modules patch, but I dislike that idea, for obvious reasons. And I heard it's hard to get it to work in production environments.
For reference, this is the github project (switch to branch scrambles for the problem at hand): https://github.com/Lykos/cube_trainer.git
And here the most relevant files:
Package.json:
{
"name": "cube-trainer",
"private": true,
"author": "Bernhard F. Brodowsky",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Lykos/cube_trainer.git"
},
"engines": {
"node": "16.x",
"npm": "8.x"
},
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --configuration production",
"build_development": "ng build --configuration development",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"test_ci": "ng test --karma-config client/karma-ci.conf.js",
"lint": "ng lint"
},
"dependencies": {
"@angular/animations": "^13.0.2",
"@angular/cdk": "^13.0.2",
"@angular/common": "^13.0.2",
"@angular/compiler": "^13.0.2",
"@angular/core": "^13.0.2",
"@angular/forms": "^13.0.2",
"@angular/material": "^13.0.2",
"@angular/platform-browser": "^13.0.2",
"@angular/platform-browser-dynamic": "^13.0.2",
"@angular/router": "^13.0.2",
"@ngrx/component-store": "^13.0.2",
"@ngrx/effects": "^13.0.2",
"@ngrx/store": "^13.0.2",
"@ngrx/store-devtools": "^13.0.2",
"@rxweb/reactive-form-validators": "^2.1.6",
"actioncable": "^5.2.6",
"angular-token": "^7.0.1",
"cubing": "^0.22.0",
"file-saver": "^2.0.5",
"ngx-cookie-service": "^13.0.1",
"ngx-filesaver": "^12.0.0",
"rxjs": "~7.4.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.0.1",
"@angular-eslint/builder": "12.6.1",
"@angular-eslint/eslint-plugin": "12.6.1",
"@angular-eslint/eslint-plugin-template": "12.6.1",
"@angular-eslint/schematics": "12.6.1",
"@angular-eslint/template-parser": "12.6.1",
"@angular/cli": "~13.0.1",
"@angular/compiler-cli": "~13.0.0",
"@ngrx/schematics": "^13.0.2",
"@types/actioncable": "^5.2.7",
"@types/chai": "^4.2.22",
"@types/file-saver": "^2.0.4",
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"@typescript-eslint/eslint-plugin": "4.28.2",
"@typescript-eslint/parser": "4.28.2",
"angular-http-server": "^1.10.0",
"chai": "^4.3.4",
"eslint": "^7.26.0",
"jasmine-core": "~3.10.0",
"karma": "~6.3.0",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"karma-mocha": "^2.0.1",
"mocha": "^9.1.3",
"typescript": "~4.4.4"
}
}
angular.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"cube-trainer": {
"projectType": "application",
"schematics": {
"@schematics/angular:application": {
"strict": true
}
},
"root": "",
"sourceRoot": "client/src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "./public",
"index": "client/src/index.html",
"main": "client/src/main.ts",
"polyfills": "client/src/polyfills.ts",
"tsConfig": "client/tsconfig.app.json",
"assets": [
"client/src/favicon.ico",
"client/src/assets"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
"client/src/styles.css"
],
"scripts": [],
"webWorkerTsConfig": "client/tsconfig.worker.json"
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "4mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "client/src/environments/environment.ts",
"with": "client/src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true,
"outputHashing": "none"
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"proxyConfig": "client/src/proxy.conf.json"
},
"configurations": {
"production": {
"browserTarget": "cube-trainer:build:production"
},
"development": {
"browserTarget": "cube-trainer:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "cube-trainer:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "client/src/test.ts",
"polyfills": "client/src/polyfills.ts",
"tsConfig": "client/tsconfig.spec.json",
"karmaConfig": "client/karma.conf.js",
"assets": [
"client/src/favicon.ico",
"client/src/assets"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css",
"client/src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"client/src/**/*.ts",
"client/src/**/*.html"
]
}
}
}
}
},
"defaultProject": "cube-trainer",
"cli": {
"defaultCollection": "@ngrx/schematics"
}
}
tsconfig.json
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "src/",
"paths": {
"@environment": ["environments/environment"],
"@shared/*": ["app/shared/*"],
"@utils/*": ["app/utils/*"],
"@store/*": ["app/store/*"],
"@effects/*": ["app/effects/*"],
"@core/*": ["app/core/*"],
"@training/*": ["app/training/*"]
},
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2017",
"module": "es2020",
"lib": [
"es2020",
"dom"
],
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"strict": true,
"skipLibCheck": true
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
tsconfig.app.json
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
}