# 前端构建

# npm

:Node Package Manager ,一个 Node.js 自带的 JS 包管理工具,于 2010 年发布。

# 命令

npm
    init                      # 初始化项目
    install [name@version]... # 安装指定的包,不指定包名则安装 package.json 里记录的所有包
            -g                # 安装到全局(默认安装到 ./node_modules 目录下)
            --save            # 安装之后记录到 package.json 的 dependencies 中
            --save-dev        # 安装之后记录到 package.json 的 devDependencies 中
    uninstall <name>...       # 卸载指定的包
           --save             # 卸载之后更新 package.json
    update <name>...          # 升级指定的包
           --save
    list                      # 列出已安装的所有包

    run <name>                # 运行 package.json 中的一个脚本

    config
          list                # 列出所有配置参数
          edit                # 编辑所有配置参数
          get     <key>       # 读取一个配置参数的值
          set     <key>=<value>
          delete  <key>
    cache
          add [name@version]... # 将指定的包加入缓存
          verify                # 检查缓存的文件,显示统计信息
          clean                 # 删除所有缓存的文件
  • 用户可执行 npm 命令,从 npm 仓库(称为 registry )下载 JS 包。

    • 默认采用的 npm 仓库地址为 https://registry.npmjs.org/ (opens new window) ,还提供了一个 Web 网站 https://www.npmjs.com/ (opens new window) 供用户访问。
    • 下载 JS 包后,有两种安装位置:
      • 默认安装到 ./node_modules 目录下。此时要通过 node_modules/.bin/<name> 的方式调用。
      • 安装到本机全局。此时会自动加入系统 PATH 路径中,可以输入命令名直接调用。
    • 用 npm 命令下载每个包时,会自动保存一份到本机的缓存目录,供全局所有用户共享。
      • 优点:重复下载一个 JS 包时,如果本机已缓存该包,则不必从 npm 仓库下载。
      • 缺点:缓存文件不会自动删除,因此会占用越来越多的磁盘。
    • 假设在本机存在 10 个 npm 项目,它们需要下载同一个 JS 包,则会先下载一份到本机的缓存目录下,然后分别拷贝到 10 个 node_modules 目录下,总共占用 11 份磁盘空间。
  • 一般构建前端项目时,执行以下命令即可:

    npm install
    npm run build
    
  • 可通过以下命令,指定自定义的 npm 仓库:

    npm install --registry https://registry.npm.taobao.org
    

    或者修改配置:

    npm config set registry http://10.0.0.1:8081/repository/npm-group/
    npm login --registry http://10.0.0.1:8081/repository/npm-group/
    
  • 上传 JS 包时,需要在 package.json 中加入配置:

    "publishConfig": {
      "registry": "https://10.0.0.1:8081/repository/npm-hosted/"
    },
    

    然后执行:

    npm login --registry https://10.0.0.1:8081/repository/npm-hosted/
    npm run build
    npm publish
    

# 配置

  • 执行 npm 命令时,会读取以下位置的配置文件:

    .npmrc            # 项目目录下的配置文件,优先级最高
    ~/.npmrc          # 当前用户的配置文件
    /etc/npmrc        # 全局的配置文件
    $NPM_HOME/npmrc   # npm 内置的配置文件,优先级最低
    
    • 配置文件采用 INI 格式,每行保存一个键值对形式的参数。
  • npmrc 配置示例:

    registry=http://10.0.0.1:8081/repository/npm-group/               # 下载 JS 包时,采用的仓库
    always-auth=true                                                  # 对所有 HTTP 请求都带上 token 认证,避免 yarn 命令不会认证
    //10.0.0.1:8081/repository/npm-group/:_authToken=NpmToken.******  # 用于登录某个 registry 的 token
    
  • 用 npm 初始化项目时,会自动在当前目录下生成一个 package.json 文件,用于记录项目用到的依赖包及其版本。内容示例:

    {
      "name": "demo",
      "version": "0.0.1",
      "description": "一个前端示例",
      "author": "",
      "private": true,        // 该项目是否私有
      "publishConfig": {
        "registry": "http://10.0.0.1:8081/repository/npm-hosted/"   // 发布 JS 包时,采用的仓库
      },
      "scripts": {            // 定义一些脚本,可以通过 npm run <name> 调用
        "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0",
        "build": "node build/build.js",
        "build:dll": "webpack --config build/webpack.dll.conf.js"
      },
      "dependencies": {       // 运行项目时的依赖包
        "js-cookie": "2.2.0", // 限制准确版本,即 2.2.0
        "vue": "^2.5.16",     // 前缀 ^ 表示限制主版本号,即 2.x.x
        "vue-router": "~3.0.1"// 前缀 ~ 表示限制主版本号和次版本号,即 3.0.x
      },
      "devDependencies": {    // 开发项目时的依赖包
        "webpack": "^3.6.0",
        "webpack-dev-server": "^2.11.5",
        "webpack-merge": "^4.1.0"
      },
      "engines": {            // 需要的 Node.js 版本
        "node": ">= 4.0.0",
        "npm": ">= 3.0.0"
      },
      "browserslist": [       // 需要的浏览器
        "> 1%",               // 全球使用率超过 1%
        "last 5 versions",    // 兼容到最后 5 个版本
        "not ie <= 8"         // 不是 IE 8 及之前的版本
      ]
    }
    
  • 从 npm v5 开始,用 npm install 安装包时会自动生成 package-lock.json 文件,用于更详细地记录每个包。内容示例:

    {
      ...
      "vue-quill-editor": {
        "version": "3.0.6",                                 // 版本号
        "resolved": "https://registry.npmjs.org/vue-quill-editor/-/vue-quill-editor-3.0.6.tgz",   // 下载地址
        "integrity": "sha1-H4VkYhHWijGoCnLLf0W7LxGbyPs=",   // 哈希值
        "requires": {                                       // 依赖包
          "object-assign": "^4.1.1",
          "quill": "^1.3.4"
        }
      }
      ...
    }
    

# yarn

:一个 JS 包管理工具。

  • 官方文档 (opens new window)
  • 于 2016 年由 Facebook 公司发布,目标是取代 npm 。
  • yarn 的用法与 npm 类似,也兼容从 npm 仓库下载包,但是有以下优点:
    • 构建速度更快。
    • 用一个 yarn.lock 文件记录已安装的所有包的版本、哈希值、依赖包,从而严格地管理依赖。

# 安装

  • 需要已安装 Node.js ,然后用 npm 安装:
    npm install --global yarn
    

# 命令

yarn                    # 相当于 npm install
    init                # 相当于 npm init
    add [name]...       # 相当于 npm install --save
        -D              # 相当于 npm install --save-dev
    remove [name]...    # 相当于 npm uninstall --save
    upgrade [name]      # 相当于 npm update --save
    list                # 相当于 npm list
    global              # 管理安装在全局作用域的包
          add
          remove
          upgrade
          list
    run <name>          # 运行 package.json 中的一个脚本

    cache
        list            # 列出所有缓存的包
        dir             # 显示缓存文件的存储目录,默认为 /usr/local/share/.cache/yarn/
        clean [name]... # 删除缓存的包

    config
        list            # 显示配置文件的内容,通常包括 /usr/local/share/.yarnrc 和 .npmrc
        get     <key>
        set     <key>=<value>
        delete  <key>

    -v                  # 显示版本号
    --verbose           # 显示详细信息
  • 执行 yarn init 时会创建一个 package.json 文件。
  • 执行 yarn install 时会创建 node_modules 目录和一个 yarn.lock 文件。
    • 如果一个包被 yarn 安装到 node_modules 目录下,则可以通过 yarn <name> 的方式调用,比 npm 更方便。
    • 建议将 yarn.lock 文件保存到 Git 仓库,从而准确记录当前安装每个包的版本。否则每次执行 yarn install 时都要分析依赖树、重新生成 yarn.lock 文件,耗时更久。
    • 存在 yarn.lock 文件时,会使得下载每个包时的 url、version 固定不变。
      • 有时用户希望修改 registry 。此时执行命令 yarn --registry xxx 没有效果,建议通过 sed 命令替换 yarn.lock 文件中的 url 。
      • yarn v2 允许执行命令 yarn --registry xxx 来覆盖 yarn.lock 文件中的 registry ,参考 issue (opens new window)

# gulp

:一个自动化构建工具,基于 Node.js ,常用于构建 JS 项目。

# 安装

npm install -g gulp

# 命令

gulp [task]...    # 执行任务(默认执行 default 任务)

# 相关概念

  • webpack :一个 JS 的打包工具,基于 Node.js 运行。

    • 它会分析 JS 项目依赖的各个模块,去除重复内容,打包成一个或多个 JS 文件,称为 bundles 。
      • 这样能减小 JS 文件的数量、体积,便于浏览器加载。不过需要浏览器支持 ES5 标准。
    • 提供了 loader 功能,用于将其它类型的文件转换成 webpack 可识别的 JS 代码。
  • Babel :一个 JS 编译器,用于将 JS 代码从 ES6+ 版本转换成 ES5 版本,便于向后兼容浏览器。

  • pnpm :一个 JS 包管理工具,用法与 npm 命令相似。特点是占磁盘少、下载耗时少。

    • 官方文档 (opens new window)
    • 于 2016 年由 Zoltan Kochan 发布。
    • 用 npm 或 yarn 命令下载一个包时,会从本机的缓存目录,拷贝到当前项目的 node_modules 目录。而 pnpm 命令不会拷贝,而是在 node_modules 目录下创建硬链接,这样占磁盘少、下载耗时少。