cssreact-nativewebpackexporeact-native-web

Use style-loader / css-loader in Expo Web (react-native-web)


I want to use codegen.macros to load different libs based on web or native output. But my web components need to load css / scss files. I really googled the heck out of me, but I can't find a running example how to adjust webpack.config.js to have a css/scss loader running with Expo Web (react-native-web).

Expo is mandatory.

It always ends up with "cant resolve ....css".

I know that react native need CSS in JS but my approach will load a different component based for web or native (ios / android).

My setup is already working pretty decent but I can't manage to load and inject a third party css file. This is my webpack.config.js file.

const createExpoWebpackConfigAsync = require('@expo/webpack-config')

module.exports = async function (env, argv) {
    const config = await createExpoWebpackConfigAsync({
            ...env,
            // Passing true will enable the default Workbox + Expo SW configuration.
        },

        argv
    );
    // Customize the config before returning it.

    config.module.rules.push({
        test: /\.((c|sa|sc)ss)$/i,
        use: [{
                loader: 'style-loader',
            },
            {
                loader: 'css-loader',
            },
            {
                loader: 'postcss-loader',
            },
            {
                loader: 'sass-loader',
            },
        ],
    }, );

    return config
}

Solution

  • I managed to fix it on my own with a lot trial and error.

    I adjusted my webpack.config.js like so.

    const createExpoWebpackConfigAsync = require('@expo/webpack-config')
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = async function (env, argv) {
        const config = await createExpoWebpackConfigAsync({
                ...env,
                // Passing true will enable the default Workbox + Expo SW configuration.
            },
    
            argv
        );
        // Customize the config before returning it.
    
        config.module.rules.push({
            test: /\.((sc)ss)$/i,
            use: [
                // Creates `style` nodes from JS strings
                MiniCssExtractPlugin.loader,
                // Translates CSS into CommonJS
                "css-loader",
                // Compiles Sass to CSS
                "sass-loader",
            ],
        }, );
    
    
        config.plugins = config.plugins.concat(
            [
                new MiniCssExtractPlugin()
            ]
        );
    
        return config
    }
    

    Since Expo uses Webpack 4 under the hood, you need to install these packages:

    package.json

      "devDependencies": {
        "@babel/core": "^7.15.0",
        "@expo/webpack-config": "^0.14.0",
        "@types/react": "~17.0.18",
        "@types/react-native": "~0.63.2",
        "@types/react-slick": "^0.23.5",
        "css-loader": "^6.2.0",
        "jest-expo": "~42.1.0",
        "mini-css-extract-plugin": "^1.6.2",
        "sass": "^1.37.5",
        "sass-loader": "^10.1.1",
        "sass-resources-loader": "^2.2.4",
        "style-loader": "^3.2.1",
        "typescript": "~4.3.5"
      },
    

    It is important to use sass-loader 10.1.1 and mini-css-extract-plugin 1.6.2.

    And I can finally import .css and .scss files in Expo Web!