Skip to content

Commit 1e9d5c7

Browse files
committed
服务端渲染webpack配置和服务端入口配置
1 parent 97fd97b commit 1e9d5c7

9 files changed

+136
-26
lines changed

Diff for: build/webpack.base.js

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const path = require('path')
22
const webpack = require('webpack')
33
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
4-
const CleanWebpackPlugin = require('clean-webpack-plugin')
54

65
module.exports = {
76
output: {
@@ -84,7 +83,6 @@ module.exports = {
8483
]
8584
},
8685
plugins: [
87-
new CleanWebpackPlugin(['dist']),
8886
new MiniCssExtractPlugin({
8987
// Options similar to the same options in webpackOptions.output
9088
// both options are optional

Diff for: build/webpack.base.server.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const path = require('path')
2+
const webpack = require('webpack')
3+
const webpackMerge = require('webpack-merge')
4+
const baseConfig = require('./webpack.base')
5+
const config = require('../config')
6+
7+
const serverPort = config.server.port
8+
9+
module.exports = webpackMerge(baseConfig, {
10+
target: 'node',
11+
entry: {
12+
app: path.join(__dirname, '../client/server-entry.js')
13+
},
14+
externals: Object.keys(require('../package.json').dependencies),
15+
output: {
16+
filename: 'server-entry.js',
17+
libraryTarget: 'commonjs2'
18+
},
19+
plugins: [
20+
new webpack.DefinePlugin({
21+
'process.env.API_BASE': JSON.stringify('http://127.0.0.1:' + serverPort)
22+
})
23+
]
24+
})

Diff for: build/webpack.dev.server.js

+13-18
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
11
const path = require('path')
2-
const webpack = require('webpack')
32
const webpackMerge = require('webpack-merge')
4-
const baseConfig = require('./webpack.base')
3+
const baseConfig = require('./webpack.base.server')
54
const config = require('../config')
65

7-
const serverPort = config.server.port
8-
96
module.exports = webpackMerge(baseConfig, {
107
mode: 'development',
11-
target: 'node',
12-
entry: {
13-
app: path.join(__dirname, '../client/server-entry.js')
14-
},
15-
externals: Object.keys(require('../package.json').dependencies),
16-
output: {
17-
filename: 'server-entry.js',
18-
libraryTarget: 'commonjs2'
19-
},
20-
plugins: [
21-
new webpack.DefinePlugin({
22-
'process.env.API_BASE': JSON.stringify('http://127.0.0.1:' + serverPort)
23-
})
24-
]
8+
devServer: {
9+
host: '0.0.0.0',
10+
compress: true,
11+
port: process.env.PORT || config.dev.serverPort,
12+
contentBase: path.join(__dirname, '../dist'),
13+
hot: true,
14+
overlay: {
15+
errors: true
16+
},
17+
publicPath: '/server-public/',
18+
disableHostCheck: true
19+
}
2520
})

Diff for: build/webpack.prod.server.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const webpackMerge = require('webpack-merge')
2-
const baseConfig = require('./webpack.dev.server')
2+
const baseConfig = require('./webpack.base.server')
33

44
module.exports = webpackMerge(baseConfig, {
55
mode: 'production'

Diff for: config/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11

22
module.exports = {
33
dev: {
4-
port: 8282
4+
port: 8282,
5+
serverPort: 8383
56
},
67
server: {
78
port: 3278

Diff for: package.json

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
"description": "react redux 服务端渲染(同构)",
55
"main": "index.js",
66
"scripts": {
7-
"dev": "webpack-dev-server --config build/webpack.dev.client.js",
7+
"dev:client": "npm run clear && webpack-dev-server --config build/webpack.dev.client.js",
8+
"dev:server": "npm run clear && webpack-dev-server --config build/webpack.dev.server.js",
89
"start": "nodemon server/server.js",
9-
"build": "webpack --config build/webpack.prod.client.js && webpack --config build/webpack.prod.server.js"
10+
"build": "npm run clear && webpack --config build/webpack.prod.client.js && webpack --config build/webpack.prod.server.js",
11+
"clear": "rimraf dist"
1012
},
1113
"repository": {
1214
"type": "git",
@@ -60,7 +62,6 @@
6062
"babel-preset-es2015-loose": "^8.0.0",
6163
"babel-preset-react": "^6.24.1",
6264
"babel-preset-stage-1": "^6.24.1",
63-
"clean-webpack-plugin": "^0.1.19",
6465
"cross-env": "^5.1.1",
6566
"css-loader": "^0.28.11",
6667
"eslint": "^4.19.1",
@@ -87,6 +88,7 @@
8788
"node-sass": "^4.9.0",
8889
"nodemon": "^1.17.4",
8990
"react-hot-loader": "^3.1.3",
91+
"rimraf": "^2.6.2",
9092
"sass-loader": "^7.0.1",
9193
"sass-resources-loader": "^1.3.3",
9294
"style-loader": "^0.21.0",

Diff for: server/server.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const app = express()
1212
app.use(bodyParser.json())
1313
app.use(bodyParser.urlencoded({ extended: false }))
1414

15-
if (true || !isDev) {
15+
if (!isDev) {
1616
const serverEntry = require('../dist/server-entry')
1717
const template = fs.readFileSync(path.join(__dirname, '../dist/server.ejs'), 'utf8')
1818
app.use('/public', express.static(path.join(__dirname, '../dist'), {

Diff for: server/util/dev-static.js

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
const axios = require('axios')
2+
const NativeModule = require('module')
3+
const vm = require('vm')
4+
const webpack = require('webpack')
5+
const MemoryFs = require('memory-fs')
6+
const path = require('path')
7+
const proxy = require('http-proxy-middleware')
8+
const globalConfig = require('../../config')
9+
const serverConfig = require('../../build/webpack.dev.server')
10+
const serverRender = require('./server-render')
11+
12+
const { port: clientDevPort } = globalConfig.dev
13+
14+
const getTemplate = () => new Promise((resolve, reject) => {
15+
axios.get(`http://localhost:${clientDevPort}/public/server.ejs`)
16+
.then(res => {
17+
resolve(res.data)
18+
})
19+
.catch(reject)
20+
})
21+
22+
/* const getServerEntry = new Promise((resolve, reject) => {
23+
axios.get(`http://localhost:${serverPort}/server-public/server-entry.js`, {
24+
headers: {
25+
'Content-Type': 'application/json;charset=UTF-8'
26+
}
27+
})
28+
.then(res => {
29+
console.log('server-entry.js')
30+
resolve(res.data)
31+
})
32+
.catch(reject)
33+
}) */
34+
/**
35+
* js字符串转换成js
36+
* @param bundle
37+
* @param filename
38+
* @returns {{exports: {}}}
39+
*/
40+
const getModuleFromString = (bundle, filename) => {
41+
const m = { exports: {} }
42+
const wrapper = NativeModule.wrap(bundle)
43+
const script = new vm.Script(wrapper, {
44+
filename: filename,
45+
displayErrors: true
46+
})
47+
const result = script.runInThisContext()
48+
result.call(m.exports, m.exports, require, m)
49+
return m
50+
}
51+
52+
const mfs = new MemoryFs
53+
const serverCompiler = webpack(serverConfig)
54+
55+
serverCompiler.outputFileSystem = mfs
56+
57+
let serverBundle
58+
59+
/**
60+
* 监听输出文件的变化 实现热更新
61+
*/
62+
serverCompiler.watch({}, (err, stats) => {
63+
if (err) throw err
64+
stats = stats.toJson()
65+
stats.errors.forEach(err => console.error(err))
66+
stats.warnings.forEach(warn => console.warn(warn))
67+
68+
const bundlePath = path.join(
69+
serverConfig.output.path,
70+
serverConfig.output.filename
71+
)
72+
const bundle = mfs.readFileSync(bundlePath, 'utf-8')
73+
const m = getModuleFromString(bundle, 'server-entry.js')
74+
serverBundle = m.exports
75+
})
76+
77+
module.exports = function (app) {
78+
app.use('/public', proxy({
79+
target: 'http://localhost:' + clientDevPort
80+
}))
81+
82+
app.get('*', function (req, res, next) {
83+
if (!serverBundle) {
84+
return res.send('waiting for compile, refresh later')
85+
}
86+
getTemplate().then(template => {
87+
return serverRender(serverBundle, template, req, res)
88+
}).catch(next)
89+
})
90+
}

Diff for: server/util/string2js.js

Whitespace-only changes.

0 commit comments

Comments
 (0)