写在开头
何谓难题?将两个水火不相容的东西强行融合在一起,将两个原理完全冲突的东西强行混合在一起的时候,需求不合理的时候
例如:通过用户的手机壳更换主题颜色
又例如:让马儿跑但是不让马儿吃草
故事的开头
后端同事,在用nodejs做个服务,但是他又做成了镜像(docker容器化了),而且是按需冷启动(即:当有人访问的时候,才启动这个服务),现阶段用的nest.js这个框架,打包出来以后,需要把整个node_modules都copy进去容器,这样导致容器很大~
此时打包工具是
webpack
开始
一开始是他在寻找webapck配置,发现各种配置行不通。打包nodejs项目不能像前端那样,直接只生成静态文件,不用携带node_modules文件夹
核心需求
想要打包nodejs时候,不携带node_modules这个完整文件夹,轻量化,把node_modules代码打包进nodejs项目源码中
国内解决方案
分层构建打包docker镜像之类的,并不能满足
问题分析
nodejs采用的是commonjs模块化方案,当然目前es6模块化也是可以跑的,在服务端运行时候,启动命令是:
node index.js
要想nodejs能顺利跑起来,起码保证,index.js代码和它的依赖都是commonjs或者es6模块化方案 这是底线
目前一些npm库是commonjs的模块化方案,并非es6模块化,我们这里暂且都看成commonjs规范。
这里同事目前用到的是wepback,那么webpack打包时候,其实会把ES6之类的模块化规范,根据配置,输出构建成自己实现的一套模块化规范。
阅读下面内容之前,可以看我之前的手写webpack系列(带源码和讲解):https://github.com/JinJieTan/Peter-/tree/master/mini-webpack
我们先复习下webpack
webpack打包过程
1.识别入口文件
2.通过逐层识别模块依赖。(Commonjs、amd或者es6的import,webpack都会对其进行分析。来获取代码的依赖)
3.webpack做的就是分析代码。转换代码,编译代码,输出代码
4.最终形成打包后的代码
我们可以看到,下面是打包后生成的图谱对象,原生的require在浏览器中是无效的
而在node环境下打包,在webpack打包后生成的代码,必须保留require这个关键字,那么就不能把node_modules里面的文件打包进源码中,否则就不是commonjs或es6模块化规范了,node的代码就跑不起来了。

问题解决思路
从上面可以看出,webpack的原理和nodejs运行、以及我们的需求,是冲突的。
所以我们不能通过webpack把node_modules代码打包进nodejs项目源码中
怎么办? 学习马斯克的思维模式,如果这个东西频繁出现问题,或者这个问题解决不了,那能不能不解决这个问题,直接跳过。弃用webpack呢?
解决
当然可以。不行就换
最终解决
弃用webpack,使用了pkg
这个库来打包解决问题
pkg是为在容器中使用而创建的
可以将 Node.js 项目打包为可执行文件,即使在未安装 Node.js 的设备上也可以运行该可执行文件
默认情况下,源代码在写入输出文件之前会预编译为 v8 字节码
使用pkg,无需下载数百个文件npm install,即可部署应用程序。将其部署为单个文件,这样我们就可以
最终打包构建成了二进制文件以及一些优化后,打包后镜像内的文件从400MB压缩到了几十MB,提升将近10倍,https://github.com/vercel/pkg
npm的未来
npm这个依赖管理 - node_modules黑洞,一直是一个诟病,我相信未来在webContainer
技术加持下,可能会找到突破方向,之前我写过一篇文章 - 面向未来的开发模式(不仅前端)
通过这个技术,进入next项目,从安装依赖到启动,只要几秒钟时间,要知道如果是在日常的开发中,这个时间可能会需要几分钟

感兴趣的可以打开手机,搜索前端巅峰公众号
,打开公众号首页,搜索文章:面向未来的前端开发模式 - 写于2021年
写在最后
在工作中遇到不合理的需求或者两个原理冲突的技术栈要果断学会放弃一些东西,每个技术都有它的使用场景,并没有好坏之分
❤️ 谢谢支持
以上便是本次分享的全部内容,希望对你有所帮助^_^
喜欢的话别忘了 分享、点赞、收藏 三连哦~。
欢迎关注公众号 前端巅峰 收货大厂一手好文章~