Starting the development server 报错和解决
问题描述
最近某个项目开发环境升级后,运行 npm start
后无法启动项目,终端始终显示 Starting the development server...
,浏览器打开 localhost: 3000 界面显示空白。
> node scripts/start.js
Starting the development server...
控制台错误截图
问题分析
因为开发环境打不开,那么大概率是构建工具的问题。这个项目使用的是 webpack 和 webpack-dev-server,近期升级的版本是 webpack4 升级到 webpack5,版本号为:
"webpack"*: "^5.64.4",
"webpack-dev-server"*: "^4.6.0",
查阅各种资料,可能得问题如下:
问题1 3000 端口占用
webpack-dev-server 默认在 3000 端口开启服务,如果其他服务已经在 3000 端口启动,那么会出现端口冲突,造成这个项目的 dev-server 无法启动。此时需要先查看 3000 端口是否占用,可以使用 lsof 命令查看:
lsof -i:3000
如果有其他服务占用端口,会显示具体的服务和信息,如下。调试时可以关闭这个服务。
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 63036 michael 26u IPv4 xxxxxx 0t0 TCP *:hbci (LISTEN)
我本地没有其他服务占用 3000 端口,应该是其他问题。
问题2 环境变量 sourcemap 配置
webpack 通常用 GENERATE_SOURCEMAP 属性,表示源代码和构建后文件的关系。如果这个配置不合适也可能打不开开发环境。可以在项目根目录中,添加 .env 文件,配置环境变量,或者在 npm 脚本中设置环境变量。
GENERATE_SOURCEMAP=false
问题3 项目入口函数
更改后,我的终端 webpack-dev-server 可以正常启动了,但是浏览器中还是空白的。
查看控制台,HTML 渲染正常,但是 JS 没有挂载到 root 根节点,问题定位到入口函数。
这个项目是多入口项目,生产环境下是一个入口(index.js),开发环境是另一个入口(index2.js),所以需要配置两个入口文件,然后根据环境不同,使用不同的入口函数。
路径文件中增加配置项 path.js
appIndexJs: resolveModule(resolveApp, 'src/index'),
applocalIndexJs: resolveModule(resolveApp, 'src/index2'),
webpack 根据环境设置入口
entry: [
isEnvDevelopment ? paths.applocalIndexJs : paths.appIndexJs,
]
此时入口函数配置正常。
问题4 模块循环引用
早期代码存在存在循环引用,其中两个模块对外暴露很多函数,不同函数互相引用,造成循环引用。
从代码层面,我先解决了循环引用的问题,这样也便于后面单元测试和模块的维护。
从 webpack 打包构建层面,可以使用 CircularDependencyPlugin 避免循环引用的问题,配置如下。
const CircularDependencyPlugin = require('circular-dependency-plugin');
plugins: [
new CircularDependencyPlugin({
exclude: /node_modules/,
include: /src/,
failOnError: false,
allowAsyncCycles: false,
cwd: process.cwd(),
}),
],
问题5 模块 splitChunk 问题
早期项目配置按需加载,打包使用 splitChunks 进行模块切分,不管生产环境还是开发环境都进行模块切分。早期的配置如下:
optimization: {
splitChunks: {
chunks: 'all',
name: false,
},
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`,
},
}
根据实际情况,在开发环境下不需要按需加载,在生产环境下需要按需加载,那么加入判断
optimization: {
splitChunks: isEnvProduction ? {
chunks: 'all',
name: false,
} : false,
runtimeChunk: isEnvProduction ? {
name: entrypoint => `runtime-${entrypoint.name}`,
} : false,
}
修改后,再次运行 npm start,终端启动显示正常,浏览器中打开 localhost: 3000 项目可以正常启动。
反思
1、webpack 注意版本号,不同项目使用版本不同,很多文档或者博客可能是 3.x 或 4.x 或 5.x 的版本,这样造成文档-代码-配置不一致。所以注意文档的时间和版本。
2、webpack 插件很多,不能做到全部精通,至少熟练使用常用插件和 loaders。刚开始学习计算机看到 webpack 配置一头雾水,现在大概知道主要配置,能解决一些常见问题了,需要不断学习积累,一定注意多使用。
参考链接
webpack 官方的插件文档
https://webpack.docschina.org/plugins/
https://webpack.docschina.org/awesome-webpack/#Webpack-Plugins
splitTrunk 配置和功能
https://juejin.cn/post/6844903680307625997
https://juejin.cn/post/6844904195737255943