由于项目引入的打包工具是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 | export default { |
1 | import _ from 'underscore'; // 这里实际上引入的是Lodash库 |
项目使用了ts,如果不在tsconfig.json中也进行声明,在开发环境下编译器会报错
【找不到模块“@/xxx”或其相应的类型声明。】
1 | //tsconfig |
需要新增的配置项为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 导出
- 静态分析——你可以决定编译时的导入和导出(静态),你只需要看源码,不需要执行它