Angular 应用内的 React 组件:导入 scss 文件

React component inside Angular app: import scss files

我正在尝试了解如何自定义 Angular CLI 构建过程,以便能够在导入 scss 文件时正确构建 React 组件。 我目前能够构建一个 Angular 项目,其中使用了一些 React 组件。那里有很多 material 解释了如何实现它(实际上很简单)。 不过,我仍然没有找到指出如何在 .tsx 文件中正确解析 scss 文件导入的文章。

例如,如果我有这个简单的 React 组件:

import * as styles from "./styles.scss";
const ReactComponentWithBrokenStyles = () => (
    <div className={styles.root}>This div won't have a class</div>
);
export default ReactComponentWithBrokenStyles;

如何编辑 Angular CLI 构建过程以正确添加将转换 .scss 文件的加载器?

我发现 指示我使用自定义构建器而不是标准构建器,这将允许我提供额外的 webpack 配置文件。我不明白的是如何在该文件中编写加载程序来解决我的问题。 默认的 Angular CLI webpack 配置已经有一个 .scss 文件的加载器,需要被 Angular 组件转换和引用,我不想覆盖它......所以我怎么能只为导入到 .tsx 文件中的 .scss 文件添加一个加载器?除了通常的正则表达式之外,有没有办法告诉 webpack 根据兄弟姐妹匹配文件?

我想这毕竟是一个精致的 webpack 问题。

注意:使用 Angular CLI v7 和 webpack 4。

真正的问题是:我需要区分 Angular .scss 文件和 React .scss 文件。

我想出的解决方案是围绕在 Webpack 的 .scss 文件规则配置中使用 oneOf,这允许更精细地区分通过相同测试(/\.scss|\.sass$/)的文件粒度方式。

所以我按照我在问题中发布的link的建议使用了@angular-builders/custom-webpack,并且我为标准Angular CLI Webpack配置创建了这个定制器:

const reactScssFilesLoaders = [
    "style-loader",
    {
        loader: "css-loader",
        options: {
            discardDuplicates: true,
            importLoaders: 1,
            modules: true,
            localIdentName: "[name]__[local]___[hash:base64:5]",
        },
    },
    "postcss-loader",
    "sass-loader"
];

/**
 * Modifies the default Webpack config so that our React components are able to
 * import styles from scss files as JS objects
 * @param {*} defaultAngularConfig The default Webpack config that comes with the NG Cli
 * @param {*} buildOptions The build options (not needed here)
 * @returns The adjusted Webpack config
 */
function customizeWebpackConfig(defaultAngularConfig, buildOptions) {
    const builtInNgScssFilesRule = defaultAngularConfig.module.rules.find(r => r.test.source.includes("scss"));
    if (!builtInNgScssFilesRule) {
        throw new Error("WTF?");
    }

    const angularScssFilesLoaders = builtInNgScssFilesRule.use;
    // We only want one top level rule for .scss files, so we need to further test
    // We want to leave normal Angular style files to the default loaders, and
    // we just want to turn styles into JS code when imported by tsx components
    builtInNgScssFilesRule.oneOf = [{
        issuer: /\.(tsx)$/,
        use: reactScssFilesLoaders
    }, {
        test: /\.(component)\.(scss)$/,
        use: angularScssFilesLoaders
    }]
    delete builtInNgScssFilesRule.exclude;
    delete builtInNgScssFilesRule.use;
    return defaultAngularConfig;
}

module.exports = customizeWebpackConfig;

很有魅力。