如何在father-build(版本不支持添加别名的情况下)中添加别名?

由于项目引入的打包工具是father-build,father 不是基于 webpack 的,无法沿用 webpack 的 alias 配置,因此需要寻找其他的方法来使用别名。

别名最终解决方案

babel打包模式:

依靠此插件babel-plugin-module-resolver
并在tsconfig设置path
tsconfig中设置了path虽然ide不会报红且可以找到路径文件,但这只是在开发环境下的。

打包后再去查看打包产物其实不会转为对应的相对路径。

配置方法:

1、首先需要安装依赖

1
yarn add --dev babel-plugin-module-resolver

2、安装完毕后在fatherrc配置文件中配置
extraBabelPlugins,
module-server中的root即为项目的根路径,也可以直接将root设置为./src
配置alias后即可实现使用@/utils(src/utils)打包后指向对应的相对路径了。
也可以配置库的别名,当引入”underscore”时,实际上引入的是”lodash”库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export default {
esm: 'babel',
cjs: 'babel',
extraBabelPlugins: [
[
'babel-plugin-import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
},
],
["module-resolver", {
"root": ["./"],
"alias": {
"@": "./src",
"underscore": "lodash"
}
}]
],
extraPostCSSPlugins: [
],
};
1
import _ from 'underscore'; // 这里实际上引入的是Lodash库

项目使用了ts,如果不在tsconfig.json中也进行声明,在开发环境下编译器会报错

【找不到模块“@/xxx”或其相应的类型声明。】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//tsconfig
{
"compilerOptions": {
"module": "esnext",
"target": "esnext",
"lib": [
"dom",
"esnext"
],
"sourceMap": true,
"allowJs": false,
"jsx": "react-jsx",
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@/*": ["./src/*"],
}
},
"include": [
"src/**/*", "test/**/*", "src/global.d.ts"
],
"exclude": [
"node_modules",
"lib",
"es",
"scripts"
]
}

需要新增的配置项为paths,只需要在paths下声明在fatherrc中配置好的别名即可解决。

rollup 打包模式

可以挂载 @rollup/plugin-alias 实现同样功能

拓展:

打包产物的区别(es,lib,dist)

在验证是否成功使用别名时,我查看了打包产物,发现打包的产物是两个文件夹即es和lib,而平时开发使用vite打包的网页打包产物只有一个dist文件。
原因其实是当前开发的项目为组件库,需要发布到npm包上面,在跨项目中被使用的时候需要考虑到不同JS模块系统的使用。
发布所有模块形态(esm,cjs),即使所有打包程序
即使webpack 和 Rollup都能解析 ES Module ,但如果使用的是 webpack 1.x,则它无法解析 ES 模块。

由于所有现代浏览器现在都支持 ES 模块 ,因此发布 ES 版本的库/包可以减少编译次数,最终可以减少向用户交付的代码。

不同打包工具的区别:(webpack,vite)

webpack

webpack是一个很棒的模块打包工具, 它被广泛接受并且主要用于构建 SPA。它提供了开箱即用的所有功能,例如代码拆分、按需加载、摇树优化等,并且它本身使用的是 CommonJS 模块系统。

RollupJS

RollupJS 还是类似于 webpack 的模块打包器。但是,RollupJS 的主要优点是它遵循 ES6 修订版中包含的代码模块的新标准化格式,因此你可以使用它来打包 ES module variant 的 library/package。但它不支持 按需加载。

Babel

Babel 是 JavaScript 的编译器,以将 ES6 代码转换为可在你的浏览器(或服务器)中运行的代码而闻名。请记住,它只是编译而不会打包你的代码。
可参考的文章
https://www.freecodecamp.org/chinese/news/anatomy-of-js-module-systems-and-building-libraries/

不同类型的 JS 模块系统

CommonJS

  • 由 Node.js 实现
  • 多用在服务器端安装模块时
  • 没有 runtime/async 模块
  • 通过 require 导入模块
  • 通过 module.exports 导出模块
  • 无法使用摇树优化,因为当你导入时会得到一个模块时,得到的是一个对象,所以属性查找在运行时进行,无法静态分析
  • 会得到一个对象的副本,因此模块本身不会实时更改
  • 循环依赖的不能优雅处理
  • 语法简单

AMD 异步模块定义

  • 由 RequireJs 实现
  • 当你在客户端(浏览器)环境中,异步加载模块时使用
  • 通过 require 实现导入
  • 语法复杂

UMD 通用模块定义

  • CommonJs + AMD 的组合(即 CommonJs 的语法 + AMD 的异步加载)
  • 可以用于 AMD/CommonJs 环境
  • UMD 还支持全局变量定义,因此,UMD 模块能够在客户端和服务器上工作。

ES modules

  • 用于服务器/客户端
  • 支持模块的 Runtime/static loading
  • 当你导入时,获得是实际对象
  • 通过 import 导入,通过 export 导出
  • 静态分析——你可以决定编译时的导入和导出(静态),你只需要看源码,不需要执行它