Skip to content

Instantly share code, notes, and snippets.

@ValentinFunk
Created March 4, 2023 12:09
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ValentinFunk/9e72f25cff23f59c890eebab9269116c to your computer and use it in GitHub Desktop.
Angular 15 upgrade issues and solutions

Solutions to Angular 15 upgrade issues

I'm documenting upgrade issues and solutions to them in case someone else runs into the same issue.

Module parse failed: Duplicate export 'renderModule'

This is because of angular/angular-cli#23866, the migration somehow didn't fix it for me.

To fix the issue go into your main.server.ts file and remove the line that exports from '@angular/platform-server'.

You can also search for '@angular/platform-server' in files and remove the line that looks like this:

export { renderModule, renderModuleFactory } from '@angular/platform-server';

Unknown version 19.6.0 of Node.js / Unknown version xxx of xxx

This is caused by outdated browserlist stuff. The Node.js one is particularly nasty because the normal browserslist update-db function doesn't fix it.

To fix this error:

  • Remove caniuse-lite from your package.json if you have it in there
  • Run npx update-browserslist-db@latest to update your caniuse-lite version.

To fix the Node.JS one:

  • Search your yarn.lock file for node-releases resolutions. These looks like this (node-releases is not indented):
    node-releases@^2.0.6:
      version "2.0.10"
      resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
      integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==
    
  • Delete all of these blocks, then run yarn to install dependencies again. Search your lockfile again and verify that there is only one 'node-releases' entry that resolves to 'version "2.0.10"'

TypeError: webpack_require(...).context is not a function

Search in files for require.context. You should find something like this in one of your test files:

// Then we find all the tests.
const context = require.context('./', true, /\.spec\.(ts|js)$/);
// And load the modules.
context.keys().map(context);

Delete this code and save. Then go into your project.json (if using nx) or angular.json and find the test configuration. Under options add a new key "include" and add the pattern you removed back as globs there. E.g. for the above:

"test": {
    "executor": "./tools/builders:karma",
    "options": {
      ...
      "main": "apps/nectar/app/main/test.ts",
      "polyfills": "apps/nectar/app/main/polyfills.ts",
      "tsConfig": "apps/nectar/tsconfig.app.json",
      "karmaConfig": "apps/nectar/karma.conf.js",
      ...
      
      // v THIS is new
      "include": [
        "apps/nectar/app/main/**/*.spec.ts",
        "apps/nectar/app/main/**/*.spec.js"
      ]
    }
  },

Tailwind issues (E.g. @layer components is used but no matching @tailwind components directive is present.)

This happens because of https://github.com/angular/angular-cli/commit/717bd03de6afe0c1f1a0f44f1a4a48e882dd07da. The issue is that previously with Angular 14 postcss was using postcss-imports which means postcss inlines the imported files into one file. This is important because otherwise the @tailwind base and @tailwind components directives would not be inlined into the final CSS file. Angular 15 changed this to use css-loader which resolves @import directives and runs postcss before inlining the CSS.

Possible solutions:

  • Move all of your tailwind CSS into a single file that has @tailwind base; at the top
  • Patch @angular-devkit/build-angular using `patch-package:

Create a file patches/@angular-devkit+build-angular+15.2.1.patch in your root folder. Install patch-package via npm/yarn (e.g. yarn install patch-package) and run yarn postinstall

diff --git a/node_modules/@angular-devkit/build-angular/src/webpack/configs/styles.js b/node_modules/@angular-devkit/build-angular/src/webpack/configs/styles.js
index e3ac726..0420db2 100755
--- a/node_modules/@angular-devkit/build-angular/src/webpack/configs/styles.js
+++ b/node_modules/@angular-devkit/build-angular/src/webpack/configs/styles.js
@@ -1,4 +1,18 @@
 "use strict";
+
+/**
+ * Explanation of patches to this file (VF):
+ *
+ * 1) Reverting https://github.com/angular/angular-cli/commit/717bd03de6afe0c1f1a0f44f1a4a48e882dd07da:
+ *   	This change was made in Angular 15 and breaks our tailwind build. The issue is that previously with
+ * 		Angular 14 postcss was using postcss-imports which means postcss inlines the imported files into one
+ * 		file. This is important because otherwise the @tailwind base and @tailwind components directives
+ * 		would not be inlined into the final CSS file. Angular 15 changed this to use css-loader which resolves
+ * 		@import directives and runs postcss **before** inlining the CSS. (undocumented breaking change)
+ * 2) Adding project root paths to imports for monorepo convenience (this was also changed at one point in angular)
+ * 3) Add postcss-nesting for tailwind CSS nesting support (setup according to tailwind docs)
+ */
+
 /**
  * @license
  * Copyright Google LLC All Rights Reserved.
@@ -98,6 +112,7 @@ function getStylesConfig(wco) {
                 ` To enable Tailwind CSS, please install the 'tailwindcss' package.`);
         }
         if (tailwindPackagePath) {
+						extraPostcssPlugins.push(require('tailwindcss/nesting')('postcss-nesting'));
             extraPostcssPlugins.push(require(tailwindPackagePath)({ config: tailwindConfigPath }));
         }
     }
@@ -111,6 +126,27 @@ function getStylesConfig(wco) {
                 }
                 : undefined,
             plugins: [
+								require('postcss-import')({
+									path: [
+										wco.projectRoot,
+										wco.root
+									],
+									resolve: (url) => (url.startsWith('~') ? url.slice(1) : url),
+									load: (filename) => {
+										return new Promise((resolve, reject) => {
+											loader.fs.readFile(filename, (err, data) => {
+												if (err) {
+													reject(err);
+
+													return;
+												}
+
+												const content = data.toString();
+												resolve(content);
+											});
+										});
+									},
+								}),
                 (0, plugins_1.PostcssCliResources)({
                     baseHref: buildOptions.baseHref,
                     deployUrl: buildOptions.deployUrl,
@@ -156,16 +192,6 @@ function getStylesConfig(wco) {
     const postCss = require('postcss');
     const postCssLoaderPath = require.resolve('postcss-loader');
     const componentStyleLoaders = [
-        {
-            loader: require.resolve('css-loader'),
-            options: {
-                url: false,
-                sourceMap: componentsSourceMap,
-                importLoaders: 1,
-                exportType: 'string',
-                esModule: false,
-            },
-        },
         {
             loader: postCssLoaderPath,
             options: {
@@ -183,7 +209,6 @@ function getStylesConfig(wco) {
             options: {
                 url: false,
                 sourceMap: !!cssSourceMap,
-                importLoaders: 1,
             },
         },
         {
@@ -263,6 +288,7 @@ function getStylesConfig(wco) {
                             // Component styles are all styles except defined global styles
                             {
                                 use: componentStyleLoaders,
+																type: 'asset/source',
                                 resourceQuery: /\?ngResource/,
                             },
                         ],

If anyone has a different solution please comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment