zoukankan      html  css  js  c++  java
  • npm run 命令解析与node_modules .bin下的文件解析

    npm run 命令解析

    在vue和react项目中,我们常常用到npm run dev命令来起本地服务,那么npm run dev到底做了什么?

    package.json文件中的字段script的每一个属性都是一个自定义的脚本命令,npm run 其实执行了package.json中的script脚本

    下面的例子,我们以vue-cli3脚手架搭建的项目为例说明,所以当我们输入命令npm run serve命令,底层相当执行vue-cli-service serve --port 8055命令

    // package.json
    "scripts": {
        "serve": "vue-cli-service serve --port 8055",
        "build": "vue-cli-service build",
        "build:test": "vue-cli-service build --mode test",
        "build:beta": "vue-cli-service build --mode beta",
        "lint": "vue-cli-service lint",
        "inspect-old": "vue-cli-service inspect --mode production > webpack.inspect.js",
        "inspect": "vue inspect --mode production",
        "inspectwebpack": "vue inspect --mode production > output.js"
    }
    
    知识点总结

    npm run如果不加任何参数,直接运行,会列出package.json里面所有可以执行的脚本命令(script字段里面的内容)。

    npm start可以运行是为了方便开发者使用,npm start会执行scripts里的start字段。 如果没有start字段则执行node server.js。

    This runs an arbitrary command specified in the package's "start" property of its "scripts" object. If no "start" property is specified on the "scripts" object, it will run node server.js.

    执行原理

    使用npm run script执行脚本的时候都会创建一个shell,然后在shell中执行指定的脚本。

    这个shell会将当前项目的可执行依赖目录(即node_modules/.bin)添加到环境变量path中,当执行之后再恢复原样。就是说脚本命令中的依赖名会直接找到node_modules/.bin下面的对应脚本,而不需要加上路径,所以scripts字段里面调用命令时不用加上路径,这就避免了全局安装NPM模块

    执行顺序
    '&' 并行执行顺序,同时执行
    "dev":"node test.js & webpack"
    
    '&&'继发顺序,执行前面之后才可以执行后面
    "dev":"node test.js && webpack"
    
    顺序钩子
    "predev":"node test_one.js",
    "dev":"node test_two.js",
    "postdev":"node test_three.js"
    

    当执行 npm run dev 的时候默认就会执行

    npm run predev && npm run dev && npm run postdev
    
    四个可以简写的脚本执行命令

    npm start === npm run start

    npm stop === npm run stop

    npm test === npm run test

    npm restart === npm run stop && npm run restart && npm run start

    使用package.json内部变量

    通过npm_package_前缀,npm脚本可以拿到npm的内部变量

    // package.json
    {
      "name":"zhy",
      "test":"node test.js"
    }
    
    test.js:
    console.log(process.env.npm_package_name) //zhy
    

    node_modules/.bin文件夹内容解析

    下面是vue-cli3搭建的项目node_modules/.bin文件夹下面的文件名

    eslint
    eslint.cmd
    lessc
    lessc.cmd
    uuid
    uuid.cmd
    vue-cli-service
    vue-cli-service.cmd
    

    对于一个npm包,有两个可执行文件,没有后缀名的是是对应unix系的shell脚本,.cmd文件对应的是windows bat脚本,内容都是用node执行一个js文件

    // vue-cli-service.cmd文件内容
    // windows bat脚本
    @IF EXIST "%~dp0
    ode.exe" (
      "%~dp0
    ode.exe"  "%~dp0..\_@vue_cli-service@3.12.1@@vuecli-serviceinvue-cli-service.js" %*
    ) ELSE (
      @SETLOCAL
      @SET PATHEXT=%PATHEXT:;.JS;=;%
      node  "%~dp0..\_@vue_cli-service@3.12.1@@vuecli-serviceinvue-cli-service.js" %*
    )
    

    这里是windows的cmd中的语法
    ~dp0指执行脚本的当前目录,这句话的意思是如果当前目录下有node.exe,就用node.exe执行... ...webpack.js文件 %*是指执行bat时命令中输入的后续参数
    否则 @SETLOCAL设置本次批处理命令中的环境变量
    PATHEXT是windows下的文件扩展名环境变量 后面的语法是从PATHEXT中删除.JS 然后执行 node ... ... webpack.js 命令,
    去除掉扩展名的作用是为了防止执行到node.js文件
    比如当前文件夹下有一个node.js文件, 如果直接执行node命令可能会默认用vscode打开这个.js文件

    // vue-cli-service文件内容
    // unix系的shell脚本
    #!/bin/sh
    basedir=$(dirname "$(echo "$0" | sed -e 's,\,/,g')")
    
    case `uname` in
        *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
    esac
    
    if [ -x "$basedir/node" ]; then
      "$basedir/node"  "$basedir/../_@vue_cli-service@3.12.1@@vue/cli-service/bin/vue-cli-service.js" "$@"
      ret=$?
    else 
      node  "$basedir/../_@vue_cli-service@3.12.1@@vue/cli-service/bin/vue-cli-service.js" "$@"
      ret=$?
    fi
    exit $ret
    
  • 相关阅读:
    软件測试培训笔记
    spring test---測试SpringMvc初识
    第1章第3节 线性表的比較
    Remove Duplicates from Sorted List leetcode
    泛型
    我的改进版2048(1)
    docker镜像和加速
    在 Azure Web 应用中创建 PHP 应用程序
    使用 Azure 门户创建 Windows 虚拟机
    使用 Azure 门户创建 Linux 虚拟机
  • 原文地址:https://www.cnblogs.com/HYZhou2018/p/12195670.html
Copyright © 2011-2022 走看看