webpack 构建 支持 ES6/7 的 node 服务开发

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 
来源:CSDN 
原文:https://blog.csdn.net/snake89322/article/details/79014108 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/oYuLian/article/details/89028667