最近在研究微服务,主要是single SPA框架。Single SPA的微服务理念,根据我的理解是这样:
- 首先创建一个主项目,主项目的工作是完成一些通用的工作,比如消息总线等
- 按需要创建或者改造n个子项目,打包成umd模块
- 在主项目中按照路由汇总所有子项目的入口信息,比如
{
name: "react app",
entry: "//localhost:8100",
render,
activeRule: genActiveRule("/react")
}
- 从主项目的index.html或者index.js启动整个app
- 当用户打开某个子页面比如/subproject1时,根据主项目中配置的subproject1的入口文件,按需加载js或者html,渲染页面,显示内容
这个中间遇到了很多webpack相关的问题:
- 启动一个app的方式有很多种,npm run dev, npm start, parcel index.html,node index.js, webpack-dev-server index.js etc, 它们分别在做什么
- 当我启动一个项目的时候,我什么时候使用的是/build下的文件,什么时候用的是开发环境的文件?
- webpack打包的文件中有一个main.js 和很多个code splitting后的chunk文件,这个main文件是怎么和那些chunk文件联系到一起的?
- code splitting的原理是什么?微服务中如何引用code splitting的项目
针对每个问题,开始寻找答案
启动一个app的方式有很多种,npm run dev, npm start, parcel index.html,node index.js, webpack-dev-server index.js etc, 它们分别在做什么 ==>汇总为问题1 到底有多少种启动app的方式,区别是什么
1. npm start/ npm run start / node *.js
npm start == npm run start = node server.js
//node.js有两个特殊脚本任务 start test,执行这两个任务可以简写的方式
npm run start == npm start //# 执行"start"指定的脚本
npm run test == npm test
//其他任务不可省略,务必以 npm run 方式执行
npm run dev //开发环境启动vue
npm run build //打包生产环境需要文件
所以很多时候package.json 文件中不需要写start的脚本,下面这个start就是多余的
"scripts": {
"start": "node server.js",
}
npm start是如何启动一个app的呢? 也就是node server.js是怎么启动一个app的,去观察一个app,会发现每个app里都有个server.js,这个文件跟页面布局这些东西都无关,会引入express,然后通过express启动一个端口,并且挂载/buid文件夹
// 初始化一个express实例
const app = express();
//设置文件目录
setup(app, {
outputPath: resolve(process.cwd(), 'build'), //process是nodejs的全局变量,process.cwd()返回当前目录
publicPath: '/'
});
// 启动app,设置端口port
app.listen(port, host, (err) => {
if (err) {
return logger.error(err.message);
}
logger.appStarted(port, prettyHost);
});
Express的核心源码就是接收request 返回response
interface Express extends Application {
request: Request;
response: Response;
即使没有webpack,也可以这样跑起来一个app
2. 利用webpack启动一个app
使用webpack的理由千千万,就不说了。 一个项目如何启用webpack呢?
- 安装webpack 依赖
npm install webpack webpack-cli webpack-dev-server
- package.json 文件中添加脚本启用webpack
"scripts": {
"build": "webpack"
}
- 执行npm run build即可
webpack命令会启动complier,根据config文件中配置的loader等打包项目文件,输出到指定的文件夹(原理 )
启动工程跑在浏览器的话使用 webpack-dev-server 工具,本身webpack-dev-server启动了一个使用express的http服务器,这个服务器与客户端采用websocket通信协议,当原始文件发生改变,webpack-dev-server会实时编译
1.webpack-dev-server伺服的是资源文件,不会对index.html的修改做出反应
2.webpack-dev-server生成的文件在内存中,因此不会呈现于目录中,生成路径由content-base指定,不会输出到output目录中。
3.默认情况下: webpack-dev-server会在content-base路径下寻找index.html作为首页
4.webpack-dev-server不是一个插件,而是一个web服务器,所以不要想当然地将其引入
3. 利用nodemon启动一个app
nodemon用来监视node.js应用程序中的任何更改并自动重启服务,非常适合用在开发环境中。nodemon将监视启动目录中的文件,如果有任何文件更改,nodemon将自动重新启动node应用程序。 nodemon是node的一个替换,所以nodemon如何启动一个app只要看node如何启动一个app,回到上面node server.js 的工作原理上
结合nodemon的使用,我也启动脚本变成
"dev": "node ./node_modules/nodemon/bin/nodemon.js",
nodemon.js 会自动寻找nodemon.json 配置文件
{
"ignore": ["**/*.test.js", "**/*.spec.js", ".git", "node_modules"],
"watch": ["server", "config"],
"exec": "npm start",
"ext": "js"
}
相当于监听了npm start的命令,项目发生改变时,重跑npm start
"start": "cross-env NODE_ENV=development ENV=development node server",
回到node server启动项目
总结 以上的npm 启动node server都是启用了node中的httpclient。 还有一些常用的容器比如nginx, tomcat可以挂载app
当我启动一个项目的时候,我什么时候使用的是/build下的文件,什么时候用的是开发环境的文件?
npm start是开发模式,使用的是开发文件。 npm run build会把代码编译到build 目录,webpack做过了压缩和优化 要想挂载/build下的文件,可以在本地使用静态服务器,也可以部署到tomcat 等容器中
静态服务器
npm install -g serve
serve -s build
,build好的东西放在服务器tomcat中webapp下的Root中,开启8080就可以看到项目内容
webpack打包的文件中有一个main.js 和很多个code splitting后的chunk文件,这个main文件是怎么和很多chunk文件联系到一起的?
Webpack提供文件分离的功能,包含两个部分: Bundle Splitting 和 Code splitting
- Bundle splitting: 创建更多更小的文件,并行加载,以获得更好的缓存效果,主要作用就是使浏览器并行下载,提高下载速度。并且运用浏览器缓存,只有代码被修改,文件名中的哈希值改变了才会去再次加载。
- Code splitting: 只加载用户最需要的部分,其余的代码都遵从懒加载的策略,主要的作用就是加快页面的加载速度,不加载不必要的代码。
main.js 是执行入口文件,*.chunk.js 是异步加载文件 打开一个页面时,通常只有主页面的内容被展示,根据设置的code splitting的策略的不同,打开一个弹窗,可能就会load进一个chunk文件,或者多个,这个饮用应该是通过相对路径引入的
code splitting的原理是什么?微服务中如何引用code splitting的项目
原理就是把需要打包在一起的代码放在一个块里,解耦没有关联的代码,这样可以有效避免只改一行代码,整个工程都要重新编译的问题。
代码拆分应该对微服务没有什么影响,有待求证