webpack-hot-middleware不会生成hot-update.json文件

时间:2018-06-17 10:30:05

标签: reactjs serverside-rendering ssr webpack-dev-middleware webpack-hot-middleware

我正在尝试使用webpack-dev-middleware启动并运行我的应用程序,webpack-hot-middle-ware,表达并做出反应。但是当我启动我的代码时,系统不会给我[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 }));
}

还需要有关服务器端渲染的任何帮助。

0 个答案:

没有答案