I'm developing nodejs with webpack, seqelize and other modules with below webpack configuration.
const path = require('path');
const webpack = require('webpack');
const fs = require('fs');
const glob = require('glob');
const CleanWebpackPlugin = require('clean-webpack-plugin');
var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = {
// entry: [ path.resolve(__dirname, 'server.js'), models ],
entry: glob.sync(path.resolve(__dirname, 'src/**/*.js')),
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
root : [path.resolve(__dirname, '')],
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js'],
modulesDirectories: ['node_modules']
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/,
query: {
cacheDirectory: true,
presets: ['es2015']
}
}, {
test: /\.json$/,
loader: 'json'
}
]
},
plugins: [
new CleanWebpackPlugin(['build'], {
root: path.resolve(__dirname, ''),
verbose: true,
dry: false,
exclude: [],
watch: true
})
],
node: {
__filename: true,
__dirname: true
},
target: 'node',
externals: nodeModules,
output: {
path: path.resolve(__dirname, 'build'),
filename: 'server.[chunkhash].js',
libraryTarget: 'commonjs'
}
}
In this case, I try to bundle the whole sources with the config and then get the bundled file named server.[chunkhash].js.
I want to move the file to server and just make work with a command like node server.[chuckhash].js, however, I got the message like below.
module.js:472
throw err;
^
Error: Cannot find module 'sequelize'
at Function.Module._resolveFilename (module.js:470:15)
at Function.Module._load (module.js:418:25)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
...
So, I tried to find the specific point to make the error, and then found out my models/index.js use the seqelize module for below codes.
import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';
import config from 'config/env';
const sequalize = new Sequelize(config.mysql.database, config.mysql.username, config.mysql.password, config.mysql.params.options);
const db = {};
fs.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== 'index.js');
})
.forEach(file => {
const model = sequalize.import(path.resolve(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if ('associate' in db[modelName]) {
db[modelName].associate(db);
}
});
db.sequelize = sequalize;
db.Sequelize = Sequelize;
export default db;
How could I fix this issue?
Actually, with the nodemodule in the same folder, there has been no error, but, make the bundled file, it will make the error.
You defined all your node_modules as externals (externals: nodeModules,). This means that webpack won't bundle any module that comes from node_modules and will just leave the imports to be resolved at runtime, just like it would when running it in Node without using webpack. For this to work you need to have the modules available wherever you run the bundle.
If you want webpack to bundle the node_modules as well, you can remove the externals option.
The externals config you're using likely came (directly or indirectly) from Backend Apps with Webpack (Part I) and you should read that blog post to understand what it's really doing and whether you need it.
Related
I'm trying to include #mycompany/package1, and #mycompany/package2 to be compiled along with the rest of my code using babel-node. Since package1 and package2 are in ES6. (Also note I'm not using Webpack)
In my jest config I added the below option into my jest config which works fine. When testing the code will compile the packages correctly
"transformIgnorePatterns": [
"/node_modules/(?!(#mycompany)/).*/"
],
But when trying to run babel-node I get errors.
In my babel.config.js
module.exports = {
presets: [
'#babel/preset-flow',
[
'#babel/preset-env',
{
targets: {
node: 8
}
}
]
],
plugins: ['#babel/plugin-proposal-class-properties']
};
I tried adding the below code to my babel.config.js but it still complains about ES6 errors within my node_modules/#mycompany/package1
I tried to include the viz package but then babel wouldn't compile my src files
include: [path.resolve(__dirname, 'node_modules/#mycompany/package1')]
include: ['/node_modules/((#mycompany)/).*/']
I tried to exclude everything but #mycompany packages but I still get transpile errors in my package1
exclude: [/node_modules\/(?!(#mycompany)\/).*/],
I tried playing with ignore but those don't seem like they are the right options based on reading the docs
I found out that we can do this with webpack to help bundle the packages with the rest of your code.
This is my webpack file for NodeJS.
const path = require('path');
const nodeExternals = require('webpack-node-externals');
const webpack = require('webpack');
const spawn = require('child_process').spawn;
const nodeEnv = process.env.NODE_ENV;
const isProduction = nodeEnv === 'production';
const compiler = webpack({
entry: ['#babel/polyfill', './src/server.js'],
output: {
path: path.resolve(__dirname, 'lib'),
filename: 'server.bundle.js',
libraryTarget: 'commonjs2'
},
externals: [
nodeExternals({
whitelist: [/#mycompany\/.*/]
})
],
plugins: plugins,
target: 'node',
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules\/(?!(#mycompany)\/).*/,
use: {
loader: 'babel-loader',
options: {
configFile: './babel.config.js'
}
}
}
]
}
});
if (isProduction) {
compiler.run((err, stats) => {
if (err) {
console.error(err);
return;
}
console.log(
stats.toString({
colors: true
})
);
});
} else {
let serverControl;
compiler.watch(
{
aggregateTimeout: 300,
poll: 1000
},
(err, stats) => {
if (serverControl) {
serverControl.kill();
}
if (err) {
console.error(err);
return;
}
console.log(
stats.toString({
colors: true
})
);
// change app.js to the relative path to the bundle created by webpack, if necessary
serverControl = spawn('node', [
path.resolve(__dirname, 'lib/server.bundle.js')
]);
serverControl.stdout.on('data', data => console.log(data.toString()));
serverControl.stderr.on('data', data => console.error(data.toString()));
}
);
}
Note the most important part is
Adding webpack-node-externals. Since this is a node.js server we don't need to bundle the node_modules.
Make sure you whitelist your package that you need to be compiled/bundled and also make sure you have your packages included to be compiled in your babel-loader
nodeExternal tells webpack know not to bundle ANY node_modules.
whitelist is saying that we should bundle the packages we listed
externals: [
nodeExternals({
whitelist: [/#mycompany\/.*/]
})
]
This line means to exclude all node_modules EXCEPT #mycompany/* packages
exclude: /node_modules\/(?!(#mycompany)\/).*/,
I am trying to use rewire with my Karma (Webpack + Typescript) unit tests. My unit tests are written in Typescript, bundled with Webpack, and then run with Karma. I keep getting the error:
PhantomJS 2.1.1 (Windows 7 0.0.0) ERROR
Error: Cannot find module "module"
at src/myTest.spec.ts:187
I looked into the code of Rewire, and the problem comes from the line
var Module = require("module"),
I know there is a Webpack Rewire plugin, but when I use it, I have the same problem as that already reported in an issue.
All my tests that don't use rewire work fine.
Here is my test file:
import rewire = require("rewire");
const decorators = rewire("./decorators");
describe('something', () => {
it('should do something', () => {
decorators.__set__('Test', () => 'hello');
// In know this is pointless, but it's just to make sure that rewire works.
expect(decorators.Test).toBe('hello');
});
});
Here is my webpack config:
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function (x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function (mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
// Our Webpack Defaults
var webpackConfig = {
entry: './src/index.ts',
target: 'node',
module: {
loaders: [
{test: /\.ts$/, loaders: ['ts-loader'], exclude: /node_modules/}
]
},
plugins: [
new webpack.BannerPlugin({banner: 'require("source-map-support").install();', raw: true, entryOnly: false}),
new webpack.optimize.UglifyJsPlugin({sourceMap: true}),
new webpack.optimize.AggressiveMergingPlugin(),
],
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index.js',
sourceMapFilename: 'index.map'
},
externals: nodeModules,
devtool: 'source-map',
resolve: {
extensions: ['.ts', '.js']
}
};
module.exports = webpackConfig;
and here is my (the relevant) part of my karma.conf.js:
frameworks: ['jasmine'],
files: [
'src/**/*.spec.ts',
'test/**/*.ts'
],
exclude: [],
webpack: {
devtool: webpackConfig.devtool,
module: webpackConfig.module,
resolve: webpackConfig.resolve,
},
webpackMiddleware: {
quiet: true,
stats: {
colors: true
}
},
preprocessors: {
'src/**/*.spec.ts': ['webpack', 'sourcemap'],
'test/**/*.ts': ['webpack', 'sourcemap']
},
I think you write this wrong
import rewire = require("rewire");
it should be
import rewire from 'rewire'
for ES6
or
const rewire = require('rewire')
for ES5
Rewriting the script in package.json worked for me:
"test": "ts-node -O '{\"module\":\"commonjs\"}' node_modules/jest/bin/jest.js"
If you get the error
SyntaxError: Unexpected token ' in JSON at position 0
this fixed it for me:
ts-node -O \"{\\\"module\\\":\\\"commonjs\\\"}\" node_modules/jest/bin/jest.js
It was not my idea. See this answer to a Github issue for a great explanation.
Given that these are the dependencies that I am using:
"react-hot-loader": "3.0.0-beta.7",
"webpack": "2.6.1",
"webpack-dev-middleware": "^1.11.0",
"webpack-hot-middleware": "^2.18.1",
"webpack-merge": "^4.1.0"
Error
patch.js:5
Uncaught ReferenceError: development is not defined
at Object.defineProperty.value (patch.js:5)
at __webpack_require__ (bootstrap 921586e…:659)
at fn (bootstrap 921586e…:85)
at Object.options.path (patch.js:1)
at __webpack_require__ (bootstrap 921586e…:659)
at fn (bootstrap 921586e…:85)
at Object.<anonymous> (process-update.js:132)
at __webpack_require__ (bootstrap 921586e…:659)
at validateFormat (bootstrap 921586e…:708)
at bootstrap 921586e…:708
You might want to either take a look at this repo
webpack-config
const FILE_PATHS = {
entry: path.resolve('./src/index.js'),
reactHotLoader: 'react-hot-loader/patch',
hmrEntry: 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000', // this is from the webpack-hot-middleware docs
output: '/' // this is the path used by webpack-dev-middleware, the docs say no real path is required, just pass in `/`
}
const devOnly = {
entry: FILE_PATHS.entry,
output: {
path: '/',
publicPath: '/assets/',
filename: 'bundle.js'
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader'
}
],
// react-hot-loader asks to include src and exclude node_modules in https://github.com/gaearon/react-hot-loader/blob/master/docs/Troubleshooting.md
include: path.resolve('./src'),
exclude: /node_modules/
},
{
test: /\.json$/,
use: [
{
loader: 'json-loader'
}
]
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-sprite-loader'
}
]
}
]
},
plugins: [
new DefinePlugin({
'process.env.NODE_ENV': 'development'
})
]
}
const hmr = {
entry: [FILE_PATHS.reactHotLoader, FILE_PATHS.hmrEntry, FILE_PATHS.entry],
plugins: [new HmrPlugin(), new NoErrorsPlugin()],
devServer: {
hot: true
}
}
const dev = merge(devOnly, hmr)
module.exports = {dev}
Express Server
// process.env.NODE_ENV = 'development'
const express = require('express')
const webpack = require('webpack')
const historyApiFallback = require('connect-history-api-fallback')
const normalizeAssets = assets => {
return Array.isArray(assets) ? assets : [assets]
}
const getLinks = assets => {
const styles = assets.filter(path => path.endsWith('.css'))
const links = styles.map(path => `<link rel="stylesheet" href="${path}" />`)
return links.join('\n')
}
const publicPath = '/assets/'
const getScripts = assets => {
const js = assets.filter(path => path.endsWith('.js'))
const scripts = js.map(path => `<script src="${path}"></script>`)
return scripts.join('\n')
}
const devMiddlewareConfig = {
serverSideRender: true,
stats: 'normal',
publicPath: publicPath,
watchOptions: {
poll: 1000,
aggregateTimeout: 300
}
}
const hotMiddlewareConfig = {
reload: true,
overlay: true
}
const devMiddlewareCreator = require('webpack-dev-middleware')
const hotMiddlewareCreator = require('webpack-hot-middleware')
const options = require('./webpack.config')
const {dev: devConfig} = options
const compiler = webpack(devConfig)
const devMiddleware = devMiddlewareCreator(compiler, devMiddlewareConfig)
const hotMiddleware = hotMiddlewareCreator(compiler, hotMiddlewareConfig)
const app = express()
app.use(devMiddleware)
app.use(hotMiddleware)
app.use(express.static(__dirname + '/public'))
app.use((req, res) => {
const stats = res.locals.webpackStats.toJson()
const assets = normalizeAssets(stats.assetsByChunkName.main)
const styles = getLinks(assets)
const scripts = getScripts(assets)
res.send(
`
<!DOCTYPE html>
<html>
<head>
<title>Webpack is crazy</title>
${styles}
</head>
<body>
<div id="app">
</div>
${scripts}
</body>
</html>
`
)
})
// app.use(historyApiFallback)
app.listen(3000, err => {
if (!err) {
console.log('Server is listening on port 3000')
}
})
The error is caused by this part of your configuration:
new DefinePlugin({
'process.env.NODE_ENV': 'development'
})
To quote the documentation:
Note that because the plugin does a direct text replacement, the value given to it must include actual quotes inside of the string itself. Typically, this is done either with either alternate quotes, such as '"production"', or by using JSON.stringify('production').
If you replace it with, for example, the following, it should work:
new DefinePlugin({
'process.env.NODE_ENV': '"development"'
})
I get a list of errors when building my TS app. I guess they are Webpack error , but I don't see how to solve them...
ERROR in ./~/errorhandler/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/errorhandler'
ERROR in ./~/serve-favicon/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/serve-favicon'
ERROR in ./~/etag/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/etag'
ERROR in ./~/express/lib/request.js
Module not found: Error: Can't resolve 'net' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/express/lib'
ERROR in ./~/express/lib/view.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/express/lib'
ERROR in ./~/send/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/send'
ERROR in ./~/destroy/index.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/destroy'
ERROR in ./~/mime/mime.js
Module not found: Error: Can't resolve 'fs' in '/Users/yves/Developments/IDEALCOMS/project/api_cockpit/node_modules/mime'
webpack.config.common.js
var webpack = require('webpack');
module.exports = {
entry: {
'app': './src/index.ts'
},
resolve: {
extensions: ['.js', '.ts']
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: 'ts-loader'
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.css$/,
loader: 'raw-loader'
}
]
},
plugins: []
};
webpack.config.dev.js
const path = require('path');
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var commonConfig = require('./webpack.config.common.js');
var env = require('./env.json');
module.exports = webpackMerge(commonConfig, {
devtool: 'cheap-module-eval-source-map',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: "/js/app/",
filename: 'bundle.js',
chunkFilename: '[id].chunk.js'
},
plugins: []
});
UPDATE ===========================
I found a solution after reading the blog post : Backend Apps with Webpack
webpack.config.dev.js
const path = require('path');
var fs = require('fs');
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var commonConfig = require('./webpack.config.common.js');
var nodeModules = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1;
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = webpackMerge(commonConfig, {
devtool: 'cheap-module-eval-source-map',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'backend.js',
chunkFilename: '[id].chunk.js'
},
externals: nodeModules,
plugins: [
new webpack.IgnorePlugin(/\.(css|less)$/),
new webpack.BannerPlugin('require("source-map-support").install();',
{ raw: true, entryOnly: false })
]
});
It seems that you have to mention the target in webpack config file.
Try this
target: 'node',
Add the above line into your webpack config file. The above config option tells webpack not to touch any built-in modules.
For some reason most page refreshes re-request the bundle.js file and it takes about 10-15-20 seconds to download from localhost. This all from localhost, and the bundle.js file is about 1mb in size. The request for this file only seems to crawl, loading a few kilobytes at a time.
Some observations:
After some digging it seems to be stalling out on the initial call to the server from __webpack_hmr, but I'm not sure as this call happens after the call to bundle.js. Below is the log of the server request flow.
It is only slow on pages that have more than one or two components, ie. anything other than the homepage. This alludes to the idea that it might be related to the hot module reloading.
The homepage will still take > 5s (sometimes 10-20) just like the other pages, but if I refresh the page with Ctrl+R, it comes back nearly instantly. If I do an address-bar refresh, it takes longer. The other pages still take just as long no matter if I Ctrl+R or do an address-bar reload...
Update: I removed the hot module replacement, and it definitely seems to be the source of the issue, as the pages load instantly without it.
Request log:
-- Response time GET / = 609ms
--> GET / 200 647ms 2.55kb
<-- GET /main.aafc9fb7f6a0c7f127edb04734d29547.css
--> GET /main.aafc9fb7f6a0c7f127edb04734d29547.css 200 17ms 3.43kb
<-- /bundle.js
--> GET /bundle.js 200 18ms 1.29mb
<-- GET /__webpack_hmr
And then in the chrome console, for this request it shows:
Here's my setup:
Using Koa as the server environment (using streaming/chunking in initial response)
Using webpack with hot module reloading
Using Vue.js as a frontend framework, with server-side rendering
bundle.js is served through the typical serve-static package
bundle.js doesn't seem to be being cached at all. Why is this?
On the Koa side of things, I started with some boilerplate package to do all this server-side rendering and such. This has been happening since I started messing around with this setup, and webpack in general, so I'm trying to get to the bottom of it. It seems to be a little random, where sometimes it will come back in < 1s, but most times it takes 10+ seconds. Sometimes 30+ seconds?!
I've also tried to use different libraries to serve the static files, but they all seem to do this.
Here is my main webpack config ('webpack.client', extended below):
'use strict'
const path = require('path')
const webpack = require('webpack')
const AssetsPlugin = require('assets-webpack-plugin')
const assetsPluginInstance = new AssetsPlugin({path: path.join(process.cwd(), 'build')})
const postcss = [
require('precss')()
//require('autoprefixer')({browsers: ['last 2 versions']}),
]
module.exports = {
entry: [
'./src/client-entry.js'
],
output: {
path: path.join(process.cwd(), 'build'),
filename: 'bundle.js',
publicPath: '/'
},
resolve: {
extensions: ['', '.vue', '.js', '.json']
},
module: {
loaders: [
{
test: /\.vue$/,
loaders: ['vue']
},
{
test: /\.js$/,
loaders: ['babel'],
exclude: [/node_modules/]
},
{
test: /\.json$/,
loaders: ['json'],
exclude: [/node_modules/]
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url?limit=10000&name=images/[hash].[ext]',
include: path.src,
},
{
test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
loader: 'url-loader',
include: path.src,
}
]
},
node: { net: 'empty', dns: 'empty' },
postcss,
vue: {
postcss,
loaders: {}
},
plugins: [
assetsPluginInstance
]
}
And also this (extends the previous):
'use strict'
const webpack = require('webpack')
const config = require('./webpack.client')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
config.entry.push('webpack-hot-middleware/client')
//config.devtool = 'inline-eval-cheap-source-map'
config.plugins = config.plugins.concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'__DEV__': true,
'process.env.NODE_ENV': JSON.stringify('development')
}),
new ExtractTextPlugin('[name].[contenthash].css')
])
config.vue.loaders = {
postcss: ExtractTextPlugin.extract(
'vue-style-loader',
'css-loader?sourceMap'
),
css: ExtractTextPlugin.extract(
'vue-style-loader',
'css-loader?sourceMap'
)
}
module.exports = config
Here is my server index.js file for Koa:
import path from 'path'
import fs from 'fs'
import Koa from 'koa'
import convert from 'koa-convert'
//import serve from 'koa-static-server'
import serveStatic from 'koa-static'
import {PassThrough} from 'stream'
import {createBundleRenderer} from 'vue-server-renderer'
import serialize from 'serialize-javascript'
import MFS from 'memory-fs'
import assets from '../build/webpack-assets'
import cookie from 'koa-cookie'
let renderer
const createRenderer = fs => {
const bundlePath = path.resolve(process.cwd(), 'build/server-bundle.js')
return createBundleRenderer(fs.readFileSync(bundlePath, 'utf-8'))
}
const app = new Koa();
app.use(cookie());
if (process.env.NODE_ENV === 'development') {
// DEVELOPMENT, with hot reload
const webpack = require('webpack')
const webpackConfig = require('../config/webpack.client.dev')
const compiler = webpack(webpackConfig)
const devMiddleware = require('koa-webpack-dev-middleware')
const hotMiddleware = require('koa-webpack-hot-middleware')
app.use(convert(devMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}
})))
app.use(convert(hotMiddleware(compiler)))
// server renderer
const serverBundleConfig = require('../config/webpack.bundle')
const serverBundleCompiler = webpack(serverBundleConfig)
const mfs = new MFS()
serverBundleCompiler.outputFileSystem = mfs
serverBundleCompiler.watch({}, (err, stats) => {
if (err) throw err
stats = stats.toJson()
stats.errors.forEach(err => console.error(err))
stats.warnings.forEach(err => console.warn(err))
renderer = createRenderer(mfs)
})
}
else {
// PRODUCTION
// use nginx to serve static files in real
//app.use(convert(serve({rootDir: path.join(process.cwd(), 'build'), rootPath: '/static'})))
app.use(serveStatic(path.join(process.cwd(), 'build')));
renderer = createRenderer(fs)
}
app.use(ctx => {
var start = new Date;
ctx.type = 'text/html; charset=utf-8'
const context = {url: ctx.url}
const title = 'Tripora';
const stream = new PassThrough()
console.log("Checking if server-side cookie exists...");
// See if request sent over an authentication token in their cookies
if(ctx.cookie && ctx.cookie.token) {
console.log("Found cookie token.");
context.token = ctx.cookie.token;
}
stream.write(`<!DOCTYPE html><html style="min-height: 100%;"><head><meta charset="utf-8"/><title>${title}</title>${assets.main.css ? `<link rel="stylesheet" href="${assets.main.css}"/>` : ''}</head><body style="min-height: 100%;">`)
const renderStream = renderer.renderToStream(context)
let firstChunk = true
renderStream.on('data', chunk => {
// we tell the request to ignore files as an initial reuqest
var isPage = ctx.url.split(".").length == 1;
if (firstChunk && context.initialState && isPage) {
stream.write(`<script>window.__INITIAL_STATE__=${serialize(context.initialState, {isJSON: true})}</script>${chunk}`)
firstChunk = false
} else {
stream.write(chunk)
}
})
renderStream.on('end', () => {
stream.write(`<script src="${assets.main.js}"></script></body></html>`)
var ms = new Date - start;
//ctx.set('X-Response-Time', ms + 'ms');
console.log("-- Response time %s %s = %sms", ctx.method, ctx.originalUrl, ms);
ctx.res.end()
})
renderStream.on('error', err => {
console.log("ERROR", err.stack);
throw new Error(`something bad happened when renderToStream: ${err}`)
})
ctx.status = 200
ctx.body = stream
})
const port = process.env.NODE_PORT || 80
app.listen(port, () => {
console.log(`==> Listening at http://localhost:${port}`)
})
Anyone know why the HMR initial request would take so long, and seem to be so random (sometimes 5s, sometimes 30 seconds)? Techneregy.