我正在尝试使我正在开发的 React 应用程序同构。这样做的一个已知问题是 webpack 加载器允许import/require
非 JavaScript 资产,例如 CSS 文件。例如
// ExampleComponent.jsx
import Select from 'react-select';
import 'react-select/dist/react-select.css';
如果使用 Express 构建应用程序,则节点将执行此导入并失败,因为它无法处理 CSS 文件,它只需要 javascript(感谢babel-register
JSX)。
解决此问题的方法之一是target: 'node'
在构建服务器应用程序(包括所有常见部分,例如组件,因为它是一个同构应用程序)时使用 webpack 中的选项来构建服务器端代码。这应该会生成一个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 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
从这里在样式加载器中。
感觉就像我非常接近完成这项工作,所以任何想法都会受到欢迎。