如何在React isomorphic应用程序中使用带有webpack的CSS模块?

时间:2016-08-14 10:44:34

标签: reactjs webpack css-modules

我使用react,react-router,express和webpack构建一个同构应用程序。现在我想使用css模块导入css。

我在import './index.css'中使用index.jsx,它在客户端上工作正常,但不能用于服务器渲染。错误是Error: Cannot find module './index.css'

组件/ index.jsx

import React, {Component, PropTypes} from 'react';
import style from './index.css';

class App extends Component {
    constructor(props, context) {
        super(props, context);
    }

    render() {
        return (
            <div id="login">
                 // ...
            </div>
        );
    }
};

export default App;

服务器/路由器/ index.js

import url from 'url';
import express from 'express';
import swig from 'swig';
import React from 'react';
import {renderToString} from 'react-dom/server';
import {match, RouterContext} from 'react-router';

import routes from '../../client/routes/routes';
import DataWrapper from '../../client/container/DataWrapper';
import data from '../module/data';

const router = express.Router();

router.get('*', async(req, res) => {
  match({
    routes,
    location: req.url
  }, async(error, redirectLocation, props) => {
    if (error) {
      res.status(500).send(error.message);
    } else if (redirectLocation) {
      res.status(302).redirect(redirectLocation.pathname + redirectLocation.search);
    } else if (props) {
      let content = renderToString(
        <DataWrapper data={data}><RouterContext {...props}/></DataWrapper>
      );
      let html = swig.renderFile('views/index.html', {
        content,
        env: process.env.NODE_ENV
      });
      res.status(200).send(html);
    } else {
      res.status(404).send('Not found');
    }
  });
});

export default router;

webpack.config.dev.js (适用于webpack-dev-server)

var webpack = require('webpack');
var config = require('./config');

module.exports = {
    devtool: 'inline-source-map',
    entry: [
        'webpack-dev-server/client?http://localhost:' + config.webpackPort,
        'webpack/hot/only-dev-server',
        './src/client/entry',
    ],
    output: {
        path: __dirname + '/public/js',
        filename: 'app.js',
        publicPath: 'http://localhost:' + config.webpackPort + '/public/js',
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoErrorsPlugin(),
        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: JSON.stringify('development')
            }
        })
    ],
    resolve: {
        extensions: ['', '.js', '.jsx', '.css']
    },
    module: {
        loaders: [{
            test: /\.jsx?$/,
            loader: 'react-hot',
            exclude: /node_modules/
        }, {
            test: /\.jsx?$/,
            loader: 'babel-loader',
            exclude: /node_modules/
        }, {
            test: /\.css$/,
            loader: 'style-loader!css-loader?modules',
            exclude: /node_modules/
        }, {
            test: /\.(png|woff|woff2|svg|ttf|eot)$/,
            loader: 'url-loader',
            exclude: /node_modules/
        }]
    }
}

2 个答案:

答案 0 :(得分:1)

在这种情况下,我建议使用webpack来编译客户端和服务器端的UI代码。只需在webpack config中设置target: "node"即可生成可在Node环境中执行的bundle。

答案 1 :(得分:0)

该文章可能有助于使用Webpack编译服务器端代码:http://jlongster.com/Backend-Apps-with-Webpack--Part-I 特别是如何使用node_modules密钥排除externals

非常简单的配置可能如下所示:

'use strict';

const path = require('path');
const fs = require('fs');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const rootDir = path.resolve(__dirname, '..');
const distDir = path.join(rootDir, 'dist');
const srcDir = path.join(rootDir, 'src');

const localStyles = new ExtractTextPlugin('local.css', { allChunks: true });

const nodeModules = fs.readdirSync('node_modules')
  .filter(dir => !dir.startsWith('.'))
  .reduce((acc, prop) => {
    acc[prop] = 'commonjs ' + prop;
    return acc;
  }, {});

const loaders = [
  {
    test: /\.(js|jsx)$/,
    include: srcDir,
    exclude: /node_modules/,
    loader: 'babel',
    query: {
      cacheDirectory: true,
    },
  },
  {
    test: /\.css$/,
    include: srcDir,
    loader: localStyles.extract(
      'style',
      'css?modules&localIdentName=[name]-[local]_[hash:base64:5]'
    ),
  },
  {
    test: /\.json$/,
    loader: 'json',
  },
];


module.exports = {

  target: 'node',

  entry: {
    server: ['server/index'],
  },

  output: {
    path: distDir,
    filename: '[name].bundle.js',
  },

  externals: nodeModules,

  module: {
    loaders,
  },

  plugins: [
    localStyles,
  ],

};

另一个解决方案(Webpack free)可以使用babel-plugin-css-modules-transform