1. 准备工作
2. 服务端程序
3. webpack 配置
3.1. 开发配置
3.2. 生产配置
4. 运行配置
5. 运行程序
6. 总结
7. 优化 level-1
7.1. 工具
7.2. 配置更改
8. 优化 level-2
9. 优化 level-3
1. 准备工作
安装 node 环境并创建项目 npm init …
安装 webpack,nodemon,concurrently,express:
npm install --save-dev webpack nodemon concurrently
npm install --save express
1
2
webpack 为最新版本,本身支持 ES6 语法。
2. 服务端程序
server.js
import express from 'express';
import test from './js/console.js';
let app = express();
let PORT = 3000;
app.get('/', (req, res) => {
res.send('Hello!');
});
let server = app.listen(PORT, function () {
let host = server.address().address;
let port = server.address().port;
console.log('Server is listening at http://%s:%s', host, port);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
console.js
export default function test () {
console.log('I am console');
}
1
2
3
3. webpack 配置
3.1. 开发配置
webpack.dev.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: [
/* 轮询文件内容 */
'webpack/hot/poll?1000',
path.resolve(__dirname, 'server.js')
],
output: {
filename: 'backend.js',
path: path.resolve(__dirname, 'dist')
},
/* 指明编译方式为 node */
target: 'async-node',
plugins: [
/* HMR plugin */
new webpack.HotModuleReplacementPlugin(),
/* 当 HMR 替换时在浏览器控制台输出对用户更友好的模块名字信息 */
new webpack.NamedModulesPlugin()
]
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
3.2. 生产配置
webpack.prod.js
const path = require('path');
const webpack = require('webpack');
const fs = require('fs');
const nodeModules = {};
fs.readdirSync('node_modules')
.filter( (catalogue) => {
return ['.bin'].indexOf(catalogue) === -1;
})
.forEach( (mod) => {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = {
entry: [
path.resolve(__dirname, 'server.js')
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
/* 告知 webpack 为 node 服务,并忽略 externals 中的模块 */
target: 'node',
externals: nodeModules,
/* __dirname 和 __filename 指向原始地址 */
context: __dirname,
node: {
__filename: false,
__dirname: false
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
4. 运行配置
package.json
...
"scripts": {
"dev-webpack": "npx webpack --config webpack.dev.js --watch &",
"dev-nodemon": "npx nodemon dist/backend.js &",
"dev": "npx concurrently \"npm run dev-webpack\" \"npm run dev-nodemon\"",
"prod": "npx webpack --config learn/graphql/webpack.prod.js"
},
...
1
2
3
4
5
6
7
8
9
10
5. 运行程序
开发,可以实现后台程序 HMR 热更新:
npm run dev
1
生产,打包后台程序:
npm run pro
1
6. 总结
优点:
前端和后台的构建工具统一,方便维护和持续集成。
缺点:
热更新开发过程会有 hot-update.js 和 hot-update.json 的缓存文件在 output 目录,暂时没发现如何消除。
开发模式下,如果 webpack 没有构建好打包程序, nodemon 命令执行无法找到构建代码。
7. 优化 level-1
7.1. 工具
rimraf 删除文件工具。
webpack-shell-plugin webpack shell 执行工具。
npm install --save-dev rimraf webpack-shell-plugin
1
7.2. 配置更改
webpack.dev.js
删除文件轮询,热更新过程中控制台会报错,但不影响程序正常执行。
新增 webpack-shell-plugin,在 webpack 构建完成后在启动 nodemon 服务。
const path = require('path');
const webpack = require('webpack');
const WebpackShellPlugin = require('webpack-shell-plugin');
module.exports = {
entry: [
path.resolve(__dirname, 'server.js')
],
output: {
filename: 'backend.js',
path: path.resolve(__dirname, 'dist')
},
/* 指明编译方式为 node */
target: 'async-node',
plugins: [
/* HMR plugin */
new webpack.HotModuleReplacementPlugin(),
/* 当 HMR 替换时在浏览器控制台输出对用户更友好的模块名字信息 */
new webpack.NamedModulesPlugin(),
new WebpackShellPlugin({
onBuildEnd: [
'npx nodemon '
+ path.resolve(__dirname, 'dist')
+ '/backend.js --watch '
+ path.resolve(__dirname, 'dist')
]
})
]
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package.json
在执行构建前先删除 hot-update 缓存文件,包括生产模式。
...
"scripts": {
"dev": "npx rimraf dist && npx webpack --config webpack.dev.js --watch",
"prod": "npx rimraf dist && npx webpack --config learn/graphql/webpack.prod.js"
},
...
1
2
3
4
5
6
7
8
8. 优化 level-2
修改 webpack.dev.js:
...
output: {
...
hotUpdateChunkFilename: '',
hotUpdateMainFilename: ''
},
...
1
2
3
4
5
6
7
8
9
9. 优化 level-3
webpack.dev.js:
增加忽略 externals 中的模块
webpack update 临时文件固定,如果命名为 '',会报错
nodemon 监控文件仅为服务器入口程序 server.bundle.js,并添加 --exitcrash 选项
重新声明上下文环境,为后续配合前端框架做准备
const path = require('path');
const webpack = require('webpack');
const fs = require('fs');
const WebpackShellPlugin = require('webpack-shell-plugin');
const WEBPACK_SERVER_JS_NAME = 'server.bundle.js';
const nodeModules = {};
fs.readdirSync('node_modules')
.filter( (catalogue) => {
return ['.bin'].indexOf(catalogue) === -1;
})
.forEach( (mod) => {
nodeModules[mod] = 'commonjs ' + mod;
});
module.exports = {
entry: [
path.resolve(__dirname, 'src/server.js')
],
output: {
filename: WEBPACK_SERVER_JS_NAME,
path: path.resolve(__dirname),
hotUpdateChunkFilename: 'hot-update.js',
hotUpdateMainFilename: 'hot-update.json'
},
/* 告知 webpack 为 node 服务,并忽略 externals 中的模块 */
target: 'node',
externals: nodeModules,
plugins: [
/* HMR plugin */
new webpack.HotModuleReplacementPlugin(),
/* 当 HMR 替换时在浏览器控制台输出对用户更友好的模块名字信息 */
new webpack.NamedModulesPlugin(),
new WebpackShellPlugin({
onBuildEnd: [
Array(
'npx',
'nodemon',
path.resolve(__dirname, WEBPACK_SERVER_JS_NAME),
'--watch',
path.resolve(__dirname, WEBPACK_SERVER_JS_NAME),
'--exitcrash'
).join(' ')
]
})
],
/* __dirname 和 __filename 指向原始地址 */
context: __dirname,
node: {
__filename: false,
__dirname: false
}
};
---------------------
作者:羽灵光Fealight
来源:优快云
原文:https://blog.youkuaiyun.com/snake89322/article/details/79014108
版权声明:本文为博主原创文章,转载请附上博文链接!