我正在尝试使用webpack-dev-middleware
webpack-hot-middle-ware、express 和 react 启动并运行我的应用程序。但是当我启动我的代码时,系统没有给我 [hash].hot-update.json 文件。当我更改代码中的某些内容时,系统会重建并提供此类文件,但文件名中的哈希值错误。这是我的代码:
开发服务器的入口点:
require('ignore-styles').default(undefined, (module, filename) => {
if ((['.png', '.jpg'].some(ext => filename.endsWith(ext)) )) {
module.exports = '/build/' + path.basename(filename);
}
});
require('babel-register')({
ignore: [ /(node_modules)/ ],
presets: ["env", "stage-0", "react"],
plugins: [
'dynamic-import-node',
'syntax-dynamic-import',
'react-loadable/babel'
]
});
const express = require('express');
const path = require('path');
const webpack = require('webpack');
const Loadable = require('react-loadable');
const webpackDevMiddleware = require('webpack-dev-middleware');
const serverRenderer = require('./server').default;
const config = require('../configs/webpack.common.js');
const compiler = webpack(config);
const app = express();
app.use(webpackDevMiddleware(compiler, { serverSideRender: true, publicPath: '/build/', }));
app.use(require("webpack-hot-middleware")(compiler));
app.use(serverRenderer());
Loadable.preloadAll().then(() => {
app.listen(3000, () => console.log('Development server is running on port 3000'));
}).catch(err => {
console.log(err);
});
我的 webpack.config.js 文件:
module.exports = [{
name: 'client',
mode: 'development',
target: 'web',
entry: ['webpack-hot-middleware/client', './app/index.js'],
output: {
path: path.join(__dirname, '../build'),
filename: 'client.js',
publicPath: '/build/',
hotUpdateChunkFilename: '[id].[hash].hot-update.js',
hotUpdateMainFilename: '[hash].hot-update.json',
},
devtool: 'source-map',
plugins: [
new ManifestPlugin({
writeToFileEmit: true,
}),
new WriteFilePlugin(),
new webpack.HotModuleReplacementPlugin(),
],
module: {
rules: [
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.(png|jpg|gif|ico|jpeg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
}
}
]
}
],
},
},
{
name: 'server',
mode: 'development',
target: 'node',
entry: './server/server.js',
externals: [nodeExternals()],
output: {
path: path.join(__dirname, '../build'),
filename: 'server.js',
libraryTarget: 'commonjs2',
publicPath: '/build/',
},
plugins: [
new WriteFilePlugin(),
],
module: {
rules: [
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.scss$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
},
{
test: /\.(png|jpg|gif|ico|jpeg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
emitFile: false
}
}
]
}
]
}
}];
我的 package.json 文件:
{
"name": "xxx",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node server/development.js",
"build": "rimraf build && NODE_ENV=production webpack --config configs/webpack.production.js --progress --profile --colors",
"prod": "node server/production.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"babel-register": "^6.26.0",
"css-loader": "^0.28.11",
"express": "^4.16.3",
"file-loader": "^1.1.11",
"ignore-styles": "^5.0.1",
"mini-css-extract-plugin": "^0.4.0",
"node-sass": "^4.9.0",
"react-hot-loader": "^4.1.2",
"rimraf": "^2.6.2",
"sass-loader": "^7.0.1",
"serialize-javascript": "^1.5.0",
"style-loader": "^0.21.0",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.6.0",
"webpack-cli": "^2.0.15",
"webpack-dev-middleware": "^3.1.3",
"webpack-hot-middleware": "^2.22.1",
"webpack-manifest-plugin": "^2.0.2",
"webpack-merge": "^4.1.2",
"webpack-node-externals": "^1.7.2",
"write-file-webpack-plugin": "^4.3.2"
},
"dependencies": {
"react": "^16.4.0",
"react-dom": "^16.4.0",
"react-helmet": "^5.2.0",
"react-loadable": "^5.3.1",
"react-redux": "^5.0.7",
"react-router-config": "^1.0.0-beta.4",
"react-router-dom": "^4.2.2",
"redux": "^4.0.0",
"redux-thunk": "^2.2.0"
}
}
和我的 server.js 文件:
import React from 'react'
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import { renderRoutes } from 'react-router-config';
import { Provider } from 'react-redux'
import { Helmet } from 'react-helmet';
import Loadable from 'react-loadable';
import serialize from 'serialize-javascript';
import configureStore from '../app/store';
import routes from '../app/routes';
import template from './template';
const store = configureStore();
const normalizeAssets = (assets) => {
return Array.isArray(assets) ? assets : [assets]
};
const searchModuleFiles = (modules, assets) => {
return modules.map(module => {
let files = [`${module}.js`, `${module}.css`];
return files.map(file => ({ file: assets[file] }));
})
};
export default (stats = null) => (req, res) => {
const context = {};
const modules = [];
let devStats = [];
let mainScript = null;
const content = renderToString(
<Provider store={store}>
<StaticRouter context={context} location={req.url}>
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
{renderRoutes(routes)}
</Loadable.Capture>
</StaticRouter>
</Provider>
);
if(!stats) {
let chunks = res.locals.webpackStats.toJson().children.filter(item => item.name === 'client')[0].assetsByChunkName;
devStats = normalizeAssets(modules.map(module => chunks[module])[0]).map(item => ({ file: `/build/${item}` }));
mainScript = { file: '/build/client.js' };
} else {
mainScript = { file: stats['main.js'] };
}
let bundles = stats ? searchModuleFiles(modules, stats)[0] : devStats;
let scripts = bundles.filter(bundle => bundle.file.endsWith('.js'));
let styles = bundles.filter(bundle => bundle.file.endsWith('.css'));
const helmet = Helmet.renderStatic();
const data = serialize(store.getState());
res.status(200).send(template({ content, data, mainScript, scripts, styles, helmet }));
}
还需要有关服务器端渲染的任何帮助。