首页 > 其他分享 >深入理解npm scripts

深入理解npm scripts

时间:2023-02-13 16:56:42浏览次数:110  
标签:npm node 深入 版本 scripts bin vite

故事要从改造公司项目脚手架说起,去年(2022年)我在部门做了vite技术分享,会后与前端基建同学聊了一下,打算将公司脚手架的构建工具由webpack升级成vite,提升开发体验,生产环境依然采用webpack。迎来的第一个问题就是如何解决node版本隔离问题?公司目前大多数项目node版本都是8.9.4,而vite要求node版本最小是12.0.0,当然开发同学可以本地自行安装高版本,但是存在以下弊端:

  • 不够优雅,开发需要手动安装
  • 污染全局,可能导致其他项目无法运行
  • 手动降级,需要换回webpack打包时,不能无缝切换
  • 心智负担,频繁切换node版本

其实这个问题已经有解决方案了,并且公司一直在使用这个方案,就是使用volta(点我了解一下)来做到项目级别的node版本控制。但是目前的问题是:volta已经用于生产环境打包,没法在一个项目里边设置多个node版本(当然手动切换版本也可以,但比较繁琐)。如果我们直接修改volta的配置,虽然可以满足运行vite版本要求 但也导致生产环境node版本被改了,结果具有不可预测性,显然不是一个好的做法。

 

那我们能否从volta、nvm、n等node版本管理解决方案上得到一些启发呢?比如在运行npm scripts时候指定node的版本,如果不存在就从网络下载zip包,解压得到可执行文件。运行指定路径的node可执行文件。实际以上这些工具就是这么干的,实现大体思路大同小异。

 

在经过一番调研后,发现其实社区已经有解决方案了,这里列举2个npm包, 这两个包都可以做到项目级别的node版本控制,使用方式和工作原理也很类似,但是他们有一个很大的区别:

nodeinstall   同时安装node与npm,可指定node下载镜像与执行路径

node 只安装node,不提供参数配置

 

在经过一番demo测试后,发现确实可以做到项目隔离,不会影响全局node。 看文档得知以下2点重要结论:

 

 

  • 下载npm包(包含了node二进制可执行文件)到本地
  • npm scripts会优先去本地node_modules中的.bin目录寻找环境变量

 

 首先验证一下结论1,查看一下node_moduls/.bin文件夹里都有啥,发现眼熟的node其实是一个软连接!其真实路径为node_modules/bin/node

 

细心的同学可能发现了,.bin目录下的文件全是软连接

 

 

接着验证结论2,分别在全局执行node -v和使用npm scripts执行node -v,结果如下:

 

可以看到,两者的node版本不一样!

 

经过一番验证,确实如文档描述一样。那么有意思的事情就来了,这里要提出几个问题:

  • 为什么终端可以运行js脚本
  • node_modules下的.bin文件夹是干什么用的
  • 为什么运行npm scripts会优先使用本地的node

带着疑问,我们一步步揭开npm的神秘面纱。

当我们输入npm run xxx,敲下回车的时候,都发生了什么?

首先我们知道一个命令想要执行,至少先要找到命令的位置,其次还得是可执行文件/脚本,那我们就顺藤摸瓜,看看npm命令的执行流程就能找到最终答案。 

 

 

 

找到npm本尊以后,这里我通过vscode断点调试,整理其核心实现如下:

将项目node_modules/.bin 与npm命令包下的node-gyp-bin添加到PATH环境变量最前端(注意追加顺序,node-gyp-bin在node_modules/.bin之前),为什么要追加到最前面?这里就要涉及到一点操作系统的知识了。

简单来说,PATH最重要的功能就是为系统查找命令/变量提供一个规则。当我们在终端输入一个指令的时候,系统就会去PATH中去查找,而查找的优先级就是从左到右。

 

 

 

 

 

设置好环境变量以后,就开始运行npm script了,核心实现可以看到是利用node子进程去执行命令 

 

 

 

通过关键源码分析得出结论:

  • npm会在运行之前为追加PATH路径
  • 然后使用node子进程执行命令

再来验证一下,是否符合预期,查看系统PATH环境变量

 

运行npm scripts时候,输出系统PATH环境变量

 

结果不言而喻,都是符合我们的预期,到这一步已经可以解释为什么我们运行node命令的时候会优先从项目目录node_modules/.bin中去查找,以及.bin目录是干什么用的

那再来说说,为什么终端能运行js代码?这里以vite为例,可以看到vite的真实路径是 node_modules/vite/bin/vite.js 

 

打开这个文件,可以看到引入眼帘的第一句就是一行类似‘注释’的代码,不要小看这一句’注释‘,他包含了两个部分:

  • #! 它叫shebang,起到标识的作用,说明这个文件可以当做脚本来运行
  • /usr/bin/env就是告诉系统可以在PATH目录中查找

所以配置#!/usr/bin/env node, 就是解决了不同的用户node路径不同的问题,可以让系统动态的去查找node来执行你的脚本文件,这也解释了为什么我们在写cli的时候需要在第一行加入这段`注释`

  

 

最后顺便谈谈 npm hooks,写了如下demo

 

 

 npm hooks处理核心代码,最关键的一句。如果当前scripts不是以pre或者post开头的,则在当前命令前后追加pre和post命令,然后顺序执行

 

 

以上疑问都已解决,看到这里相信你对npm的执行流程应该有一个清晰的认识了。

那最终我是如何实现node版本隔离的呢?由于`node`这个npm包无法指定node安装路径,这会导致运行所有npm scripts都会默认去.bin目录寻找node,在部署生产环境的时候不希望使用本地node。

前面说过nodeinstall可以指定execPath参数,利用这个就可以指定一个node安装路径,这样就不会影响到项目其他npm脚本原有的执行流程。有了node执行文件,接下来就是如何解决在运行npm scripts的时候指定我们安装的本地node,

这里使用node子进程的fork方法就可以实现,其可以指定execPath(既node可执行文件位置),这样就达到了最终效果。

 

标签:npm,node,深入,版本,scripts,bin,vite
From: https://www.cnblogs.com/zt123123/p/17115099.html

相关文章

  • 深入浅出SQL优化器原理
    深入浅出SQL优化器原理https://mp.weixin.qq.com/s/u7waqx0JhFnrg8I6TJEHDQ深入浅出SQL优化器原理原创 郭泽晖(索月) 阿里云数据库 2023-02-1017:00 发表于北京摘......
  • 一步一步教你apache深入优化
    Aache深入优化一、在Centos01上安装apache服务,在Centos02配置DNS服务器使用域名www.stz.com1、在Centos01上安装apache服务配置网站1)切换光盘2)挂载光盘解压源代码程序[root@......
  • Nginx - 深入理解nginx的处理请求、进程关系和配置文件重载
    概述Nginx的系统学习整理的第三篇博客,主要介绍nginx的应用场景和架构基础,以便更好的理解,再生产环境中进行性能调优。Nginx的三个主要应用场景1.静态资源服务,通过本地文......
  • 从简单到复杂:深入了解 JavaScript 中的 this 绑定规则
    前言大家好,我是CoderBin,在JavaScript中,this是一个非常重要的概念,属于进阶知识,不管是在面试还是日常开发中都是非常常用的。所以本次给大家总结了关于this的绑定规则,来帮助......
  • Apache 网页深入优化
    一、Apache网页优化概述•在企业中,部署Apache后只采用默认的配置参数,会引发网站很多问题,换言之默认配置是针对以前较低的服务器配置的,以前的配置已经不适用当今互联网时代......
  • 【前端工具】nodejs+npm+vue 安装(windows)
    预备先看看这几个是干嘛的,相互的关系是啥。nodejs是语言,类比到php。npm是个包管理,类比到composer。vue是个框架,类比到laravel。webpack是个打包工具。先下载nodejs......
  • 【Shell】环境变量深入
    目录自定义系统环境变量自定义系统环境变量全局配置文件/etc/profile应用场景:当前用户进入Shell环境初始化的时候会加载全局配置文件/etc/profile里面的环境变量,供......
  • C语言--深入理解指针与地址
    1.初学指针的军规--Type*类型的指针只保存Type类型变量的地址--禁止不同类型的指针相互赋值注意:指针保存的地址必须是有效地址eg:inti=10;floa......
  • 深入解读.NET MAUI音乐播放器项目(一):概述与架构
    系列文章将分步解读音乐播放器核心业务及代码:深入解读.NETMAUI音乐播放器项目(一):概述与架构深入解读.NETMAUI音乐播放器项目(二):播放内核深入解读.NETMAUI音乐播放器项......
  • 深入解读.NET MAUI音乐播放器项目(二):播放内核
    播放控制服务IMusicControlService:播放控制类,用于当前平台播放器对象的操作,对当前所播放曲目的暂停/播放,下一首/上一首,快进快退(寻迹),随机、单曲模式等功能的控制。播放......