I'm upgrading an Angular application from version 9 to 13. I'm using Shakapacker 8, Rails 6.0.6.1, and Angular 13. After updating to Angular 13, I'm getting this error when building:
ERROR in ./app/javascript/packs/webcli.ts
Module build failed (from ./node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected][email protected]_psw5ptd3rrza3n5xpobodp2hkm/node_modules/@ngtools/webpack/src/index.js):
Error: No module factory available for dependency type: CssDependency
at /home/me/the-app-flder/node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected][email protected]_psw5ptd3rrza3n5xpobodp2hkm/node_modules/@ngtools/webpack/src/ivy/loader.js:81:18
at runNextTicks (node:internal/process/task_queues:60:5)
at process.processImmediate (node:internal/timers:454:9)
This is happening for all the entrypoint app components. I've tried using style-loader, but it didn't generate the CSS and no errors were reported. The TypeScript compilation works and the JS files are emitted. I also tried using package versions released around the same time as Angular 13, but still get the same issue.
Here is my package.json:
{
"name": "p1tsa",
"version": "3.5",
"private": true,
"type": "module",
"packageManager": "[email protected]+sha512.76e2379760a4328ec4415815bcd6628dee727af3779aaa4c914e3944156c4299921a89f976381ee107d41f12cfa4b66681ca9c718f0668fa0831ed4c6d8ba56c",
"resolutions": {
"@types/react": "16.9.31"
},
"browserslist": [
"defaults"
],
"dependencies": {
"@angular/animations": "^13.4.0",
"@angular/common": "^13.4.0",
"@angular/compiler": "^13.4.0",
"@angular/compiler-cli": "^13.4.0",
"@angular/core": "^13.4.0",
"@angular/forms": "^13.4.0",
"@angular/localize": "^13.4.0",
"@angular/platform-browser": "^13.4.0",
"@angular/platform-browser-dynamic": "^13.4.0",
"@angular/router": "^13.4.0",
"@babel/core": "7",
"@babel/plugin-transform-class-properties": "^7.25.9",
"@babel/plugin-transform-destructuring": "^7.25.9",
"@babel/plugin-transform-regenerator": "^7.25.9",
"@babel/plugin-transform-runtime": "7",
"@babel/preset-env": "7",
"@babel/preset-react": "^7.25.9",
"@babel/runtime": "7",
"@ng-select/ng-select": "v8.x",
"@ngtools/webpack": "13.3.11",
"@popperjs/core": "^2.11.8",
"@sweetalert2/ngx-sweetalert2": "^11.0.0",
"angular-plotly.js": "^3.1.0",
"babel-loader": "8",
"babel-plugin-macros": "^3.1.0",
"bootstrap": "4.4.1",
"braces": "^2.3.2",
"compression-webpack-plugin": "9",
"core-js": "3",
"css-loader": "6.8.1",
"d3": "^6.7.0",
"daterangepicker": "^3.1.0",
"deep-extend": "^0.5.1",
"extend": "^3.0.2",
"fstream": "^1.0.12",
"html-loader": "1.1.0",
"http-proxy-agent": "^4.0.1",
"jquery": "3.5.0",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"lodash.mergewith": "^4.6.2",
"lodash.template": "^4.5.0",
"mem": "^4.3.0",
"mini-css-extract-plugin": "2.6.0",
"minimatch": "^3.1.2",
"mixin-deep": "^1.3.2",
"moment": "^2.30.1",
"moment-duration-format": "^2.3.2",
"moment-timezone": "^0.5.46",
"ngx-bootstrap": "^8.0.0",
"node-forge": "^1.3.1",
"plotly.js": "^1.58.5",
"plotly.js-dist-min": "1.58.4",
"popper.js": "^1.16.0",
"prop-types": "^15.8.1",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"reflect-metadata": "^0.1.14",
"rxjs": "^7.4.0",
"sass": "1.26.3",
"sass-loader": "8.0.2",
"serialize-javascript": "^3.1.0",
"set-value": "^2.0.1",
"shakapacker": "8.0.0",
"style-loader": "1.1.3",
"sweetalert": "^2.1.2",
"sweetalert2": "^11.15.0",
"terser-webpack-plugin": "5",
"ts-loader": "^6.2.2",
"tslib": "^2.0.0",
"typescript": ">=4.4.2 <4.5",
"webpack": "5",
"webpack-assets-manifest": "^5.2.1",
"webpack-merge": "5",
"webpack-sources": "^3.2.3",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-class-static-block": "^7.26.0",
"@babel/plugin-transform-for-of": "^7.25.9",
"@babel/plugin-transform-object-rest-spread": "^7.25.9",
"@babel/plugin-transform-private-methods": "^7.25.9",
"@babel/plugin-transform-private-property-in-object": "^7.25.9",
"@types/babel__core": "7",
"@types/d3": "^6.7.0",
"@types/moment-duration-format": "^2.2.6",
"@types/node": "12.12.2",
"@types/node-forge": "^1.3.11",
"@types/react": "16.9.31",
"@types/react-dom": "^16.9.24",
"@types/webpack": "5",
"autoprefixer": "9.8.8",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-preset-react": "^6.24.1",
"brotli-webpack-plugin": "^1.1.0",
"caniuse-lite": "^1.0.30000697",
"cosmiconfig": "^8.1.0",
"cssnano": "4.1.11",
"exports-loader": "0.7.0",
"extract-loader": "5.0.1",
"html-minify-loader": "^1.4.0",
"postcss": "^7.0.1",
"postcss-import": "12.0.1",
"postcss-loader": "7.1.0",
"postcss-preset-env": "6.7.0",
"raw-loader": "^4.0.2",
"shallow-clone": "^3.0.1",
"ts-node": ">=10",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "4"
}
}
And my webpack config:
import shakapacker from 'shakapacker';
import { AngularWebpackPlugin } from '@ngtools/webpack';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import linkerPlugin from '@angular/compiler-cli/linker/babel';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import sass from 'sass';
const { generateWebpackConfig } = shakapacker;
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const webpackConfig = generateWebpackConfig();
const { resolve, plugins, module } = webpackConfig;
const extensions = [
'.js',
'.ts',
'.tsx',
'.jsx',
'.scss',
'.sass',
'.css',
'.html'
];
webpackConfig.mode = process.env.NODE_ENV || process.env.RAILS_ENV || 'production';
resolve.preferRelative = true;
Object.assign(resolve, {
extensions: [
...new Set([
...extensions,
...(resolve.extensions || [])
])
],
mainFiles: ['index'],
// // mainFields: ['module', 'main'], // Exclude 'browser'
fullySpecified: false,
enforceExtension: false,
});
plugins.push(
new AngularWebpackPlugin({
tsconfig: path.resolve(__dirname, '../../tsconfig.json')
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
);
module.rules.push({
test: /\.[jt]sx$/,
loader: 'babel-loader',
exclude: /node_modules/,
});
module.rules.push({
test: /\.[cm]?js$/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
compact: false,
plugins: [linkerPlugin],
},
},
})
module.rules.push({
test: /\.m?js$/,
include: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
compact: false
},
},
})
const tsJsRule = module.rules.find(r => `${r.test}` === `${/\.(js|jsx|mjs|ts|tsx|coffee)?(\.erb)?$/}`);
tsJsRule.test = /\.[jt]s/;
tsJsRule.use = ['@ngtools/webpack'];
export default webpackConfig;
And my shakapacker.yml:
default: &default
source_path: app/javascript
source_entry_path: packs
nested_entries: false
css_extract_ignore_order_warnings: false
public_root_path: public
public_output_path: packs
cache_path: tmp/shakapacker
webpack_compile_output: true
shakapacker_precompile: true
additional_paths: []
cache_manifest: false
webpack_loader: 'babel'
ensure_consistent_versioning: true
compiler_strategy: digest
useContentHash: false
development:
<<: *default
compile: true
compiler_strategy: mtime
dev_server:
host: localhost
port: 3035
hmr: false
inline_css: false
client:
overlay: true
compress: true
allowed_hosts: 'auto'
pretty: true
headers:
'Access-Control-Allow-Origin': '*'
static:
watch:
ignored: '**/node_modules/**'
test:
<<: *default
compile: true
public_output_path: packs-test
production:
<<: *default
compile: false
useContentHash: true
cache_manifest: true
Any ideas what could be causing this CssDependency error or how to resolve it? Let me know if any other details would be helpful.