在我的React / Webpack应用程序中,我遇到的问题是我的HTML没有引用所包含的样式表 - 我基本了解了为什么会发生这种情况,但我并没有完全了解具体情况而且我绝对不会知道解决问题的最佳方法。这是低谷......
我的应用程序使用服务器端呈现,我有两个单独的Webpack配置,一个用于客户端(webpack.config.js
),另一个用于服务器(webpack.server.config.js
)。在我的应用程序组件中,我require()
两个样式表来自Node模块,如下所示:
require("bootstrap/dist/css/bootstrap.css")
require("react-quill/dist/quill.snow.css")
并通过Webpack的public/css/vendor/main.css
将它们编译成单独的样式表(ExtractTextPlugin
)。这是客户端webpack.config
:
const webpack = require("webpack"),
ExtractTextPlugin = require("extract-text-webpack-plugin"),
webpackConfig = {
"entry": "./src/index.jsx",
"module": {
"loaders": [
{
"exclude": /node_modules/,
"loader": "babel-loader",
"query": { "presets": ["react", "es2015", "stage-2"] },
"test": /\.jsx?$/
},
{
"exclude": /node_modules/,
"loader": "babel-loader",
"test": /\.js$/
},
{
"loader": ExtractTextPlugin.extract({
"fallback": "style-loader",
"use": "css-loader?modules&importLoaders=1&localIdentName=[local]"
}),
"test": /\.css$/
},
{
"loader": "file-loader?name=public/fonts/[name].[ext]",
"test": /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/
}
]
},
"output": {
"filename": "./public/bundle.js",
"publicPath": "/"
},
"plugins": [
new webpack.DefinePlugin({
"API_URL": JSON.stringify(process.env.API_URL || "http://localhost:4000/api/v1"),
"IS_STAGING": JSON.stringify(process.env.IS_STAGING || "false"),
"NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development")
}),
new ExtractTextPlugin({
filename: "public/css/vendor/[name].css",
disable: false,
allChunks: true
})
]
}
module.exports = webpackConfig
到目前为止,这么好。事实上,如果我在开发模式下运行我的应用程序(它不使用我的webpack.server.config
而是使用babel-register
来动态处理服务器端编译),则HTML的样式正确。但是,当我运行使用webpack.server.config.js
构建服务器端软件包的生产版本时,就会遇到问题。这是webpack.server.config.js
,其中包含我确定不正确的代码:
const webpack = require("webpack"),
fs = require("fs"),
path = require("path"),
ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
"entry": path.resolve(__dirname, "index.js"),
"externals": fs.readdirSync(path.resolve(__dirname, "node_modules")).concat(["react-dom/server", "react/addons"]).reduce((ext, mod) => {
ext[mod] = `commonjs ${mod}`
return ext
}, {}),
"module": {
"loaders": [
{
"exclude": /node_modules/,
"loader": "babel-loader",
"query": { "presets": ["react", "es2015", "stage-2"] },
"test": /\.jsx$/
},
{
"exclude": /node_modules/,
"loader": "babel-loader",
"query": { "presets": ["react", "es2015", "stage-2"] },
"test": /\.js$/
},
{
"loader": ExtractTextPlugin.extract({
"fallback": "style-loader",
"use": "css-loader?modules&importLoaders=1&localIdentName=[local]"
}),
"test": /\.css$/
},
{
"loader": "file-loader?name=public/fonts/[name].[ext]",
"test": /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/
}
]
},
"node": {
"__dirname": true,
"__filename": true
},
"output": {
"filename": "server.bundle.js"
},
"target": "node",
"plugins": [
new webpack.EnvironmentPlugin({
"GIT_COMMIT": "No git commit hash provided",
"BUILD_DATE": "No build date provided"
}),
new ExtractTextPlugin({
filename: "public/css/vendor/[name].css",
disable: false,
allChunks: true
})
],
}
作为参考,build
命令是:
"build:client": "webpack --config webpack.config.js",
"build:server": "webpack --config webpack.server.config.js",
"build": "npm run build:client && npm run build:server"
问题在于重复使用ExtractTextPlugin
和file-loader
。当此代码用于构建服务器端配置时,不会抛出任何错误,但是当我启动应用程序时,样式表不适用于HTML(即使它们存在)。现在我很确定这种冗余是造成问题的原因 - 我做了一个测试,我离开了服务器配置,应用程序运行得很好,虽然我失去了服务器端渲染的好处,我需要 - 但我不喜欢我不明白解决这个问题的最佳方法。
由于我的组件中有require()
,服务器端Webpack正在寻找那些并且需要知道如何处理它们,而只是重用ExtractTextPlugin
(如客户端 - side config)导致样式失败,即使应用程序运行时文件存在。
解决此问题的最佳做法是什么?我的问题/问题是否清楚?