UNPKG

3.37 kBJavaScriptView Raw
1'use strict'
2
3process.env.BABEL_ENV = 'development'
4process.env.NODE_ENV = 'development'
5
6process.on('unhandledRejection', err => {
7 throw err
8})
9
10const ora = require('ora')
11const webpack = require('webpack')
12const { getFreePort, localIp } = require('@mara/devkit')
13const config = require('../config')
14const getContext = require('../config/context')
15const getEntry = require('../lib/entry')
16const getWebpackConfig = require('../webpack/webpack.dev.conf')
17const createDevServerConfig = require('../webpack/webpack.devServer.conf')
18const prehandleConfig = require('../lib/prehandleConfig')
19const DevServerPlugin = require('../lib/DevServerPlugin')
20const DEFAULT_PORT = parseInt(process.env.PORT, 10) || config.devServer.port
21const PROTOCOL = config.devServer.https === true ? 'https' : 'http'
22const spinner = ora('Starting development server...')
23
24function getDevCompiler(webpackConf) {
25 addDevClientToEntry(webpackConf, [
26 // 使用 CRA 提供的 client,展示更友好的错误信息
27 require.resolve('../lib/hotDevClient')
28 ])
29
30 return webpack(webpackConf)
31}
32
33function addDevClientToEntry(config, devClient) {
34 const { entry } = config
35
36 if (typeof entry === 'object' && !Array.isArray(entry)) {
37 Object.keys(entry).forEach(key => {
38 entry[key] = devClient.concat(entry[key])
39 })
40 } else if (typeof entry === 'function') {
41 config.entry = entry(devClient)
42 } else {
43 config.entry = devClient.concat(entry)
44 }
45}
46
47function createDevServer(webpackConf, opts) {
48 const host = localIp()
49 const proxyConfig = config.devServer.proxy
50 const serverConf = createDevServerConfig({
51 entry: opts.entry,
52 host: host,
53 proxy: proxyConfig,
54 protocol: PROTOCOL,
55 publicPath: opts.publicPath
56 })
57 const compiler = getDevCompiler(webpackConf)
58
59 // 确保在 new DevServer 前执行
60 // 避免错过事件钩子
61 new DevServerPlugin({
62 port: opts.port,
63 entry: opts.entry,
64 useYarn: config.useYarn,
65 spinner,
66 protocol: PROTOCOL,
67 root: config.paths.app,
68 host: host,
69 openBrowser: config.devServer.open,
70 useTypeScript: config.useTypeScript,
71 onTsError(severity, errors) {
72 devServer.sockWrite(devServer.sockets, `${severity}s`, errors)
73 }
74 }).apply(compiler)
75
76 const DevServer = require('webpack-dev-server')
77 const devServer = new DevServer(compiler, serverConf)
78
79 return devServer
80}
81
82async function setup(entryInput) {
83 const context = await getContext({
84 version: require(config.paths.packageJson).version,
85 view: entryInput.entry
86 })
87
88 return { context, ...entryInput }
89}
90
91async function server({ context, entry }) {
92 spinner.start()
93
94 let webpackConfig = getWebpackConfig(context, spinner)
95
96 webpackConfig = prehandleConfig({
97 command: 'dev',
98 webpackConfig,
99 entry: entry
100 })
101
102 const port = await getFreePort(DEFAULT_PORT)
103 const devServer = createDevServer(webpackConfig, {
104 entry,
105 port,
106 publicPath: context.publicPath
107 })
108
109 // Ctrl + C 触发
110 ;['SIGINT', 'SIGTERM'].forEach(sig => {
111 process.on(sig, () => {
112 devServer.close()
113 process.exit()
114 })
115 })
116
117 // 指定 listen host 0.0.0.0 允许来自 ip 或 localhost 的访问
118 return devServer.listen(port, '0.0.0.0', err => {
119 if (err) return console.log(err)
120 })
121}
122
123module.exports = function runServe(argv) {
124 return getEntry(argv)
125 .then(setup)
126 .then(server)
127}