专栏名称: qize
前端交互开发工程师
目录
相关文章推荐
51好读  ›  专栏  ›  qize

Lerna+webpack+juction来拆分组件库为多个单独的npm包

qize  · 掘金  · 前端  · 2018-02-08 02:56

正文

本文作者:IMWeb DeepKolos 原文出处: IMWeb社区 未经同意,禁止转载

前不久发布了 vc-popup组件集 , 但是那时候完全只是展示没有如何使用的教程, 因为当时急于发布出来, 实在不妥, 抱歉~

既然是想自己东西可以让别人方便使用, 那就是打包成npm的包咯, 但是考虑 vc-popup 仅仅是popup的组件集, 不是完整的组件库, 所以很多时候用户仅仅想使用某个 popup , 那么其他 popup 也打包进去, 就浪费带宽了, 所以需要一个每个 popup 单独发布到npm上去, 但是把依赖分开的时候之后开发就是带来不便, 比如一个包更新了, 需要在另一个手动更新, 为了解决这个不便, 就是 Lerna 登场的时候了, 用来方便开发和管理多个 package ~

但是自己实践的过程当中遇到一些问题和还有踩过一些坑, 所以在这里记录, 不过在开始之前, 先提一下 vc-popup 的更新

12-08: imgView支持懒加载图片,从加载状态的预设图片到加载完成的src同步变化~

popup-img-viewer2.gif


安装Lerna

目前知道3种办法, 如果在使用 vscode 同学, 使用 cnpm 时候附带 --by=npm 可以避免 rg.exe 吃CPU的问题, 同理可以设置为 --by=yarn , 一些包使用 cnpm 安装有问题的时候, 就可以使用让 cnpm 仅仅做下载, 安装交给 npm/yarn

> npm i -g lerna
> cnpm i -g lerna --by=npm
> yarn global add lerna

初始化一个demo

在日常使用输入命令的时候常用 && 加快效率, 自己输入的次数多了, 才发现命令行相比于界面的优点在于可以串联多个简单的任务, 这个学期开始学习操作系统, 发现有个类似的名词 单道批处理系统 CMD批处理脚本 , 所以不言而喻咯~ 摁 {enter} 键的时候想想还有什么命令可以提前敲进去的

还有一个优点是, 命令是基于 字符组合 的确定, 而非 界面位置 , 所以界面需要层叠, 命名不需要, 字符组合容量大

> mkdir lerna-demo && cd lerna-demo && lerna init

前面因为需要穿插 cnpm 所以安装部分没有串联

由于键盘右边 shift 键位问题, 其实输入&&的时候并不是那么顺畅, 可以通过 AHK 来做转接, 我一般用笔记本键盘的时候按 aand{space} 生成 &&{space} , 自己做的键盘, 因为调整过shift的位置就还是按&&

生成的查看生成的文件和目录

> ls
lerna.json  package.json  packages

分别查看文件内容

> head lerna.json && head package.json
{
  "lerna": "2.5.1",
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0"
}
{
        "devDependencies": {
                "lerna": "^2.5.1"
        }
}

然后新建目录s

> cd packages && mkdir module-0 module-1 module-2

初始化 package.json

> cd module-0 && npm init -y && cd ../module-1 && npm init -y && cd ../module-2 && npm init -y
Wrote to D:\DEV\Github\demo\lerna-demo\packages\module-0\package.json:

{
  "name": "module-0",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}


Wrote to D:\DEV\Github\demo\lerna-demo\packages\module-1\package.json:

{
  "name": "module-1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}


Wrote to D:\DEV\Github\demo\lerna-demo\packages\module-2\package.json:

{
  "name": "module-2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

初始化每个module的 index.js

> echo export default require('./package.json').name > index.js && cat index.js > ../module-0/index.js && cat index.js > ../module-1/index.js

然后在 lerna-demo 新建index.js并编辑, 因为lerna会维护的是packages/*之间的依赖, 这里的 index.js 直接填写 module-2 的路径

> cd ../.. && code index.js
const msg = require('./packages/module-2')

console.log(msg);

设置 module 之间依赖, 现在 require 的时候就可以直接填写对应的 module

修改module-1的index.js

export default 
  require('./package.json').name 
  + 'depends on [' + require('module-0').default + ']'

修改module-2的index.js

export default 
  require('./package.json').name 
  + 'depends on [' + require('module-1').default + ']'

思考

正常途径如何添加npm包的依赖? yarn add modue-name

有什么结果? 会从npm仓库下载该包下来, 解压到 node_modules/module-name , 然后处理 packsage.json 依赖

那么是否意味着 Lerna 也会有这个类似的操作? 如果现在在开发module-2, 但是发现是module-1的bug, 把module-1的bug修改了, 需要发布一下到npm, 然后module-2再更新module-1的依赖, 那么可以猜测 Leran 通过某种手段让这个更新同步自动化了

那么基于猜测可以进行验证咯~ 先看手册, 查查这个类似的操作是什么~

2017-11-14_112623.png

看Example就很清晰知道的了, 那么开始生成依赖

> lerna add module-0 --scope=module-1
> lerna add module-1 --scope=module-2

那么可以预计操作结果是, module-2的 node_modules module-1 的文件夹,并且包含了其内容, module-1同理

2017-12-16_092625.png

那么就可以猜测如何实现了

是递归复制文件? 验证一下 那么现在修改一下 module-0/index.js 然后,查看 module-1/node_modules/module-0/index.js , module-2 同理

module-0/index.js 该为如下

export default 
  require('./package.json').name + ' edited'

2017-12-16_093248.png

OK, 自动修改是同步更新的, 所以不是, 记得自己看linux的教程的时候有个工具是相关的, ln , 但是我使用的是, 文件系统是 NTFS

> ver
Microsoft Windows [Version 10.0.15063]
> ln --help                                                                   
用法:ln [选项]... [-T] 目标 链接名     (第一种格式)                                         
 或:ln [选项]... 目标         (第二种格式)                                              
 或:ln [选项]... 目标... 目录 (第三种格式)                                                
 或:ln [选项]... -t 目录 目标...      (第四种格式)                                        
In the 1st form, create a link to TARGET with the name LINK_NAME.             
In the 2nd form, create a link to TARGET in the current directory.            
In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.           
Create hard links by default, symbolic links with --symbolic.                 
By default, each destination (name of new link) should not already exist.     
When creating hard links, each TARGET must exist.  Symbolic links             
can hold arbitrary text; if later resolved, a relative link is                
interpreted in relation to its parent directory.                 
--more

但是我用的是windows哦, 那么猜测是通过windows的工具来实现的, 这个时候, 突然我想到了多次重装系统在网上习得的技巧

> mklink --help
The syntax of the command is incorrect.
Creates a symbolic link.

MKLINK [[/D] | [/H] | [/J]] Link Target

        /D      Creates a directory symbolic link.  Default is a file
                symbolic link.
        /H      Creates a hard link instead of a symbolic link.
        /J      Creates a Directory Junction.
        Link    Specifies the new symbolic link name.
        Target  Specifies the path (relative or absolute) that the new link
                refers to.

之前重装系统多了, 会通过mklink把C盘的Users Juction 到D盘去, 之后每次恢复系统的时候一些程序的配置也就不用重新设置的了, 具体可以参考 网上的教程 , 需要装系统的时候操作的(文件解压出来, 但是还没重启, 启动安装的时候), 记得好像不能在系统安装之后操作

来验证咯, 这时候就不能使用 ls -all 来查看了(安装了cygwin, 并且把bin目录放在path里了, 所以可以用), 而是需要使用 dir

2017-12-16_095526.png

所以, lerna在windows下是通过建立 Juction 来解决 依赖包同步更新 的问题~ linux的话, 也就不言而喻咯, 使用的应该是类似的工具 ln ~

通过 webpack 设置 babel 转码, 然后通过 lerna-demo/index.out.js 来验证结果咯~

> webpack && node index.out.js
Hash: 3378d33b254656002585
Version: webpack 3.10.0
Time: 1031ms
       Asset     Size  Chunks             Chunk Names
index.out.js  4.14 kB       0  [emitted]  main
   [0] ./index.js 83 bytes {0} [built]
   [1] ./packages/module-2/index.js 183 bytes {0} [built]
   [2] ./packages/module-2/package.json 233 bytes {0} [built]
   [3] ./packages/module-1/index.js 183 bytes {0} [built]
   [4] ./packages/module-1/package.json 233 bytes {0} [built]
   [5] ./packages/module-0/index.js 141 bytes {0} [built]
   [6] ./packages/module-0/package.json 196 bytes {0} [built]
module-2 depends on [module-1 depends on [module-0 edited]]

结果就出来了, demo测试通过 再想一下改造 vc-popup 的时候会可能出现什么问题? Lerna解决的是在 packages/* 的依赖, 也就是回到了例子的问题了

const msg = require('./packages/module-2')

console.log(msg);

这里说明的是在不在packages文件夹内就不能享受依赖更新同步的福利了

开工

任何对 试验性 的改造, 都推荐新建分支里面进行~







请到「今天看啥」查看全文