脚本宝典收集整理的这篇文章主要介绍了当 webpack 遇上 symlink,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
在开发若干个有相互依赖关系的库的时候,通常都会采用 syMLink 的方式互相引用,比较典型的一种场景就是使用 lerna 开发多个 package 。
lerna 简介
lerna 是用于管理拥有多个 package 的 JavaScript 项目,其典型目录结构为
lerna-repo/
packages/
package1/
package.json
package2/
package.json
package.json
lerna.json
packages 目录下面就是各个 package 了。
lerna 有两个比较常用的命令:
lerna clean
lerna bootstrap
lerna clean
用于清理 packages ,会删掉各个 package 下面的 node_modules 目录。
lerna bootstrap
用于处理各个 package 的依赖,处理步骤为:
根据各个 package 下 package.JSON 里面的 dePEndencies 和 devDependencies 配置,使用 symlink 在各个 package 的 node_modules 下面建立引用关系。
在每个 package 下执行 npm run prepare
。
symlink 的问题
假设 package 下面有一个包 pkg1
,依赖 package 下面的另一个包 pkg2
。
运行 lerna bootstrap
之后, pkg1/node_modules
下就会出现 pkg2
的 symlink 。
如果使用 webpack 系列工具来编译运行 pkg1
,由于 webpack loader 判断路径默认是按照真实路径来的,所以 pkg2
对应到的路径是 [project root]/package/pkg2
,而不是 [project root]/package/pkg1/node_modules/pkg2
。
这样一来,如果需要 pkg2
中的源码过 pkg1
的 loader (比如 pkg2
中的 ES6 代码过 pkg1
的 babel-loader
),就需要在 webpack 相应 loader 配置中加上这个特殊的路径匹配,这和不涉及 symlink
的真实场景
存在较大差异。
同时,很多配置(比如 postcssrc
、 babelrc
、 eslintrc
等)是以 resolve 到的文件去解析的,比如要用 babel 编译 pkg2
下面的 [project root]/package/pkg2/src/DiaLOG.es6
源码,会按照如下目录顺序查找 babelrc
配置:
[project root]/package/pkg2/src/
[project root]/package/pkg2/
[project root]/package/
[project root]/
...
而此时很可能希望能在 [project root]/package/pkg1/
目录下寻找 babelrc 配置。
所以此时其实很希望 webpack loader 基于 symlink 的路径去解析判断 include / exclude
等配置,而不是按照真实文件的路径。
resolve.symlinks
webpack 提供了 resolve.symlinks
来解决这个问题,具体参见官方文档。
新的问题
虽然使用 symlink 解决了基准路径
的问题,但是还存在另外的问题。
如果 pkg2
依赖了 babel-runtime
,那么在 pkg1
的配置中就要注意不要让 babel-runtime
过 babel-loader
了,不然 babel 可能会在 babel-runtime
的源码里面插入一些 ES6 的代码。
如果 pkg1
和 pkg2
同时依赖了第三方模块 externalPkg3
,那么在 lerna bootstrap
之后,会存在两个 externalPkg3
:
[project root]/package/pkg1/node_modules/externalPkg3
[project root]/package/pkg1/node_modules/pkg2/node_modules/externalPkg3 -> [project root]/package/pkg2/node_modules/externalPkg3
而 externalPkg3
里面有个 module 提供了全局的 object :
const obj = {};
export function register(name, value) {
obj[name] = value;
}
export function getValue(name) {
return obj[name];
}
此时 pkg1
和 pkg2
会用各自的 obj
对象,如果 pkg1
中想用 pkg2
注册进去的 value
,就会拿不到。
可以考虑在 lerna.json
中配置 commands.bootstrap.ignore
为 ["pkg2"]
,在 lerna bootstrap
的时候不安装 pkg2
的依赖,使得最终只会有一个 externalPkg3
:
[project root]/package/pkg1/node_modules/externalPkg3
这种方式肯定不会是万能的,具体怎么做还要看真正的场景,可能还得各种配置互相配合才能解决问题。
以上是脚本宝典为你收集整理的当 webpack 遇上 symlink全部内容,希望文章能够帮你解决当 webpack 遇上 symlink所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。