如何最佳配置React组件库与Webpack、TypeScript、CSS模块和SASS?

3
我是为其他项目配置React组件库以供重用。我想使用以下内容:
  • 使用Typescript编写组件
  • Css模块化
  • Sass
  • 使用Webpack进行打包
这是我的webpack配置:
    const childProcess = require('child_process');

const path = require('path');
const url = require('url');

const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const loadersConf = require('./webpack.loaders');

const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env

const targetIsRun = NPM_TARGET === 'run';
const targetIsTest = NPM_TARGET === 'test';
const targetIsStats = NPM_TARGET === 'stats';
const targetIsDevServer = NPM_TARGET === 'dev-server';

const DEV = targetIsRun || targetIsStats || targetIsDevServer;

const STANDARD_EXCLUDE = [
    path.join(__dirname, 'node_modules'),
];

// These files will be imported in every sass file
const sassResourcesPaths = [
    path.resolve(__dirname, 'src/styles/abstracts/_variables.sass'),
    path.resolve(__dirname, 'src/styles/abstracts/_mixins.sass'),
];

const config = {
    module: {
        rules: loadersConf,
    },
    resolve: {
        modules: [
            'node_modules',
            path.resolve(__dirname),
        ],
        extensions: ['.js', '.jsx', '.ts', '.tsx', '.css', '.scss'],
    },
    performance: {
        hints: 'warning',
    },
    target: 'web',
    plugins: [
        new webpack.DefinePlugin({
            COMMIT_HASH: JSON.stringify(childProcess.execSync('git rev-parse HEAD || echo dev').toString()),
        }),
        new MiniCssExtractPlugin({
            filename: '[name].[contentHash].css',
            chunkFilename: '[name].[contentHash].css',
        }),
    ],
};

if (DEV) {
    config.mode = 'development';
    config.devtool = 'source-map';
}


const env = {};
if (DEV) {
} else {
    env.NODE_ENV = JSON.stringify('production');
}

config.plugins.push(new webpack.DefinePlugin({
    'process.env': env,
}));

module.exports = config;

这是webpack的加载器:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const STANDARD_EXCLUDE = [
    path.join(__dirname, 'node_modules'),
];

const NPM_TARGET = process.env.npm_lifecycle_event; //eslint-disable-line no-process-env
const targetIsRun = NPM_TARGET === 'run';
const targetIsTest = NPM_TARGET === 'test';
const targetIsStats = NPM_TARGET === 'stats';
const targetIsDevServer = NPM_TARGET === 'dev-server';

const DEV = targetIsRun || targetIsStats || targetIsDevServer;

// noinspection WebpackConfigHighlighting
module.exports = [
    {
        test: /\.(js|jsx|ts|tsx)?$/,
        exclude: STANDARD_EXCLUDE,
        use: {
            loader: 'babel-loader',
            options: {
                cacheDirectory: true,

                // Babel configuration is in .babelrc because jest requires it to be there.
            },
        },
    },
    {
        type: 'javascript/auto',
        test: /\.json$/,
        include: [
            path.resolve(__dirname, 'i18n'),
        ],
        exclude: [/en\.json$/],
        use: [
            {
                loader: 'file-loader?name=i18n/[name].[hash].[ext]',
            },
        ],
    },
    // ==========
    // = Styles =
    // ==========
    // Global CSS (from node_modules)
    // ==============================
    {
        test: /\.css/,
        include: path.resolve(__dirname, "node_modules"),
        use: [
            MiniCssExtractPlugin.loader,
            {
                loader: "style-loader"
            },
            {
                loader: 'css-loader'
            }
        ]
    },
    {
        test: /\.(sc|sa|c)ss$/,
        exclude: /\.st.css$/, //This must appear before the "oneOf" property
        use: [
            MiniCssExtractPlugin.loader,
            'style-loader',
            'css-modules-typescript-loader',
            {
                loader: 'css-loader',
                options: {
                    importLoaders: 2,
                    modules: true,
                    camelCase: "dashes",
                    localIdentName: DEV
                        ? '[name]__[local]___[hash:base64:5]'
                        : '_[hash:base64:5]',
                },
            },
            {
                loader: "postcss-loader",
                options: {
                    sourceMap: "inline",
                    extract: true,
                }
            },
            "sass-loader",
        ],
    },
    {
        test: /\.(png|eot|tiff|svg|woff2|woff|ttf|gif|mp3|jpg)$/,
        use: [
            {
                loader: 'file-loader',
                options: {
                    name: 'files/[hash].[ext]',
                },
            },
            {
                loader: 'image-webpack-loader',
                options: {},
            },
        ],
    },
];

Babel 配置:

const config = {
    presets: [
        ['@babel/preset-env', {
            targets: {
                chrome: 66,
                firefox: 60,
                edge: 42,
                safari: 12,
            },
            modules: false,
            corejs: 3,
            useBuiltIns: 'usage',
            shippedProposals: true,
        }],
        ['@babel/preset-react', {
            useBuiltIns: true,
        }],
        ['@babel/typescript', {
            allExtensions: true,
            isTSX: true,
        }],
    ],
    plugins: [
        '@babel/plugin-transform-runtime',
        '@babel/plugin-syntax-dynamic-import',
        '@babel/proposal-class-properties',
        '@babel/proposal-object-rest-spread',
        '@babel/plugin-proposal-optional-chaining',
        ['module-resolver', {
            root: ['./src', './test'],
        }],
    ],
};

// Jest needs module transformation
config.env = {
    test: {
        presets: config.presets,
        plugins: config.plugins,
    },
};
config.env.test.presets[0][1].modules = 'auto';

module.exports = config;

这是该库的演示组件:
import React from 'react';

const styles = require('./style.scss');

type Props = {
    children?: React.ReactNode;
    openLeft?: boolean;
    openUp?: boolean;
    id?: string;
    ariaLabel: string;
    customStyles?: object;
}

export default class Button extends React.PureComponent<Props> {
    public render() {
        return (
            <button className={styles.test}>
                {this.props.children}
            </button>
        );
    }
}

那么,这是开发构建命令:

"build": "cross-env NODE_ENV=production webpack --display-error-details --verbose",
    "run": "webpack --progress --watch",

当我使用这个库时:
import ExampleComponent from 'mylibrary';

当我运行BUILD或RUN命令时,JavaScript已经构建完成,但SCSS没有。因此,在我的另一个项目中,构建过程会抛出错误:
can not find module './style.scss'

这个错误发生在ExampleComponent中。

请告诉我如何解决它。非常感谢!


我觉得你的webpack配置有点复杂,但是我知道cssMiniExtractPlugin和style-loader不能一起使用。另外,加载器的顺序也很重要。 - undefined
1个回答

0
这是我用于样式部分的webpack配置:
{
            test: /\.s?css$/,
            use: [
                {
                    loader: MiniCssExtractPlugin.loader
                },
                {
                    loader: 'css-loader'
                },
                {
                    loader: 'postcss-loader',
                    options: {
                        config: {
                            path: 'postcss.config.js'
                        }
                    }
                },
                {
                    loader: 'sass-loader'
                },
            ]
        }

在我的postcss.config.js文件中:

module.exports = {
    plugins: [
      require('autoprefixer')
    ]
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接