node.js - 使用 webpack 构建 (React) 同构 web 应用程序的服务器部分,包括 CSS 样式加载器

标签 node.js reactjs webpack isomorphic-javascript webpack-style-loader

我正在尝试制作一个我正在开发的同构 React 应用程序。 known problems with doing this之一是 webpack 加载器允许 import/require 非 JavaScript 资源,例如 CSS 文件。例如

// ExampleComponent.jsx
import Select from 'react-select';
import 'react-select/dist/react-select.css';

如果使用 Express 构建应用程序,则 Node 将进行此导入并失败,因为它无法处理 CSS 文件,它只需要 javascript(并且感谢 babel-register JSX)。

解决这个问题的方法之一是在构建服务器应用程序时使用 webpack 中的 target: 'node' 选项(其中包括所有公共(public)部分,例如组件,因为它是同构应用程序) )来构建服务器端代码。这应该会生成一个可以由 Node 运行的 server.js

注意:我知道还有其他方法可以解决这个特定问题(例如不使用 import/require 来包含非 javascript 的任何内容,但在现阶段这是不切实际的)此应用程序的开发。

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

module.exports = [
  // Client build
  {
    entry: {
      'bundle.min': [
        'bootstrap-webpack!./bootstrap.config.js',
        'babel-polyfill',
        './client/index.jsx'
      ],
      'bundle': [
        'bootstrap-webpack!./bootstrap.config.js',
        'babel-polyfill',
        './client/index.jsx'
      ]
    },
    output: {
      path: './dist',
      filename: '[name].js'
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        include: /\.min\.js$/,
        minimize: true
      })
    ],
    module: {
      loaders: [
        {
          test: /\.jsx$/,
          loader: 'babel-loader',
          exclude: /node_modules/,
          query: {
            plugins: ['transform-runtime'],
            presets: ['react', 'es2015', 'stage-0']
          }
        },
        {
          test: /\.js$/,
          loader: 'babel-loader',
          exclude: /node_modules/,
          query: {
            plugins: ['transform-runtime'],
            presets: ['es2015', 'stage-0']
          }
        },
        {
          test: /\.css$/,
          loader: 'style-loader!css-loader'
        },
        { test: /\.png$/,
          loader: "url-loader?limit=100000"
        },

        // Bootstrap
        {
          test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'url?limit=10000&mimetype=application/font-woff'},
        {
          test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'url?limit=10000&mimetype=application/octet-stream'
        },
        {
          test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'file'
        },
        {
          test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'url?limit=10000&mimetype=image/svg+xml'
        }
      ]
    },
    resolve: {
      extensions: ['', '.js', '.jsx', '.json']
    }
  },

  // Server build
  {
    entry: './server/server.jsx',
    target: 'node',
    node: {
      console: false,
      global: false,
      process: false,
      Buffer: false,
      __filename: false,
      __dirname: false,
    },
    output: {
      path: './dist',
      filename: 'server.js',
    },
    module: {
      loaders: [
        {
          test: /\.jsx$/,
          loader: 'babel-loader',
          exclude: /node_modules/,
          query: {
            plugins: ['transform-runtime'],
            presets: ['react', 'es2015', 'stage-0']
          }
        },
        {
          test: /\.js$/,
          loader: 'babel-loader',
          exclude: /node_modules/,
          query: {
            plugins: ['transform-runtime'],
            presets: ['es2015', 'stage-0']
          }
        },
        {
          test: /\.json$/,
          loader: 'json-loader'
        },
        {
          test: /\.css$/,
          loader: 'style-loader!css-loader'
        },
        { test: /\.png$/,
          loader: "url-loader?limit=100000"
        },

        // Bootstrap
        {
          test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'url?limit=10000&mimetype=application/font-woff'},
        {
          test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'url?limit=10000&mimetype=application/octet-stream'
        },
        {
          test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'file'
        },
        {
          test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
          loader: 'url?limit=10000&mimetype=image/svg+xml'
        }
      ]
    },
    resolve: {
      extensions: ['', '.js', '.jsx', '.json']
    }
  }
];

问题是样式加载器使用了 window,而这显然在 Node 环境中不存在。

$ node dist/server.js
/Users/dpwrussell/Checkout/ExampleApp/dist/server.js:25925
            return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
                                       ^

ReferenceError: window is not defined

来自here在样式加载器中。

感觉我已经非常接近完成这项工作了,所以欢迎任何想法。

最佳答案

答案是不要使用style-loader在你的服务器构建中:它的唯一目的是获取 CSS,将其变成 <style>元素,并将其插入到 DOM 中。大多数人似乎使用 ExtractTextPlugin收集他们的 CSS 以包含在服务器端。

关于node.js - 使用 webpack 构建 (React) 同构 web 应用程序的服务器部分,包括 CSS 样式加载器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36020514/

相关文章:

css - 如何使用 React webpack 设置 bootstrap 4 scss

javascript - 在React中循环父对象内的对象

c# - 如何配置 .netcore 代理连接到 webpack 以使用 HTTP 而不是 HTTPS

node.js - 未使用 REST API 在 Node Js 中调用函数

node.js - 如何获取并回复收到的特定短信信息?

node.js - LoopBack 用户特定的数据过滤/访问

node.js - Mongoose: ref 自定义字段名称

reactjs - 请向我解释一下这个奇怪的 React 语法

javascript - 如何在node.js和react中的某些数字后显示分页点

javascript - 在 webpack 中传递与环境相关的变量