diff --git a/packages/web/src/utils/web.config.ts b/packages/web/src/utils/web.config.ts index d712638bcb..da8e35dee6 100644 --- a/packages/web/src/utils/web.config.ts +++ b/packages/web/src/utils/web.config.ts @@ -5,7 +5,7 @@ import { getCommonConfig } from './third-party/cli-files/models/webpack-configs/ import { getStylesConfig } from './third-party/cli-files/models/webpack-configs/styles'; import { Configuration } from 'webpack'; import { LoggerApi } from '@angular-devkit/core/src/logger'; -import { basename, resolve } from 'path'; +import { basename, resolve, posix } from 'path'; import { WebBuildBuilderOptions } from '../builders/build/build.impl'; import { convertBuildOptions } from './normalize'; import { readTsConfig } from '@nrwl/workspace'; @@ -13,6 +13,7 @@ import { getBaseWebpackPartial } from './config'; import { IndexHtmlWebpackPlugin } from './third-party/cli-files/plugins/index-html-webpack-plugin'; import { generateEntryPoints } from './third-party/cli-files/utilities/package-chunk-sort'; import { ScriptTarget } from 'typescript'; +import { getHashDigest, interpolateName } from 'loader-utils'; const MiniCssExtractPlugin = require('mini-css-extract-plugin'); @@ -135,6 +136,15 @@ function getStylesPartial( }); return rule; }); + + const loaderModulesOptions = { + modules: { + mode: 'local', + getLocalIdent: getCSSModuleLocalIdent, + }, + importLoaders: 1, + }; + partial.module.rules = [ { test: /\.css$|\.scss$|\.sass$|\.less$|\.styl$/, @@ -149,10 +159,7 @@ function getStylesPartial( }, { loader: require.resolve('css-loader'), - options: { - modules: true, - importLoaders: 1, - }, + options: loaderModulesOptions, }, ], }, @@ -166,10 +173,7 @@ function getStylesPartial( }, { loader: require.resolve('css-loader'), - options: { - modules: true, - importLoaders: 1, - }, + options: loaderModulesOptions, }, { loader: require.resolve('sass-loader') }, ], @@ -184,10 +188,7 @@ function getStylesPartial( }, { loader: require.resolve('css-loader'), - options: { - modules: true, - importLoaders: 1, - }, + options: loaderModulesOptions, }, { loader: require.resolve('less-loader') }, ], @@ -202,10 +203,7 @@ function getStylesPartial( }, { loader: require.resolve('css-loader'), - options: { - modules: true, - importLoaders: 1, - }, + options: loaderModulesOptions, }, { loader: require.resolve('stylus-loader') }, ], @@ -251,3 +249,27 @@ function getPolyfillsPartial( return config; } + +function getCSSModuleLocalIdent(context, localIdentName, localName, options) { + // Use the filename or folder name, based on some uses the index.js / index.module.(css|scss|sass) project style + const fileNameOrFolder = context.resourcePath.match( + /index\.module\.(css|scss|sass|styl)$/ + ) + ? '[folder]' + : '[name]'; + // Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique. + const hash = getHashDigest( + posix.relative(context.rootContext, context.resourcePath) + localName, + 'md5', + 'base64', + 5 + ); + // Use loaderUtils to find the file or folder name + const className = interpolateName( + context, + fileNameOrFolder + '_' + localName + '__' + hash, + options + ); + // Remove the .module that appears in every classname when based on the file and replace all "." with "_". + return className.replace('.module_', '_').replace(/\./g, '_'); +}