从 javascript 包的子文件夹导入
Importing from subfolders for a javascript package
我有一个包含多个文件夹的打字稿库。每个文件夹都包含一个 index.ts 文件,该文件导出一些业务逻辑。我正在尝试将其与汇总捆绑在一起以在呼叫站点上实现此行为:
import { Button, ButtonProps } from 'my-lib/button'
import { Input, Textarea } from 'my-lib/input'
import { Row, Column } from 'my-lib/grid'
这是目录结构:
我在 src/
下有一个主要 index.ts
,其中包含:
export * from './button';
export * from './input';
export * from './grid';
有了这个风格,我可以做到:
import { Button, Input, InputProps, Row, Column } from 'my-lib'
但我不想要这个。我想通过它们的命名空间访问每个模块。如果我从 index.ts
文件中删除导出,我所能做的就是:
import { Button } from 'my-lib/dist/button'
这是我以前没见过的。添加 dist/
到 import 语句意味着我通过相对路径访问模块。我想要 my-lib/Button
.
我正在使用汇总。我尝试使用 alias
插件但没有用。下面是我的汇总配置:
const customResolver = resolve({
extensions: ['ts'],
});
export default {
input: `src/index.ts`,
output: [
{
file: pkg.main,
format: 'cjs',
sourcemap: true,
// plugins: [terser()],
},
{
file: pkg.module,
format: 'es',
sourcemap: true,
plugins: [terser()],
},
],
// Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash')
external: [],
watch: {
include: 'src/**',
},
plugins: [
// Allow json resolution
json(),
// Compile TypeScript files
typescript({ useTsconfigDeclarationDir: true }),
// Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
commonjs(),
// Allow node_modules resolution, so you can use 'external' to control
// which external modules to include in the bundle
// https://github.com/rollup/rollup-plugin-node-resolve#usage
resolve(),
// Resolve source maps to the original source
sourceMaps(),
alias({
entries: [
{ find: 'my-lib/button', replacement: './dist/button' },
{ find: 'my-lib/input', replacement: './dist/input' },
{ find: 'my-lib/grid', replacement: './dist/grid' },
],
customResolver,
}),
],
};
这是 tsconfig
文件:
{
"compilerOptions": {
"target": "es5",
"module": "ES6",
"lib": ["ES2017", "ES7", "ES6", "DOM"],
"declaration": true,
"declarationDir": "dist",
"outDir": "dist",
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowJs": false,
"moduleResolution": "node",
"resolveJsonModule": true,
"baseUrl": "./src",
"paths": {
"my-lib/button": ["./src/button"],
"my-lib/input": ["./src/input"],
"my-lib/grid": ["./src/grid"]
}
},
"exclude": ["node_modules", "dist", "**/*.test.ts"],
"include": ["src/**/*.ts"]
}
我不知道如何使用汇总实现与 lodash/xxx
或 material-ui/yyy
相同的结构。
人们建议使用别名或命名导出,但我做不到。
最接近我的问题的是下面的问题:
我想实现同样的事情,但使用 typescript
和 rollup
。
我想我漏掉了什么,谢谢。
首先,两者的唯一区别
import { Button } from 'my-lib/dist/button'
和
import { Button } from 'my-lib/button'
只是多了一层目录。
曾经说过,在 tsconfig.json
文件中包含 "outDir": "dist",
之前,您需要将 dist/
添加到 import
语句中。
确实,您举的两个库都随根目录中的文件一起分发:lodash directly has js
files in the root, while material-ui 在其 tsconfig.json
文件中没有 outDir
选项(这意味着写入输出文件到根目录)。
希望对您有所帮助。
经过多次试验和错误后,我能够通过输入列表、使用 preserveModules and preserveModulesRoot 选项和一个简单的安装后脚本来实现此功能。
这是我的 rollup.config.js
const options = {
input: [
'src/index.ts',
'src/api/index.ts',
'src/components/index.ts',
'src/contexts/index.ts',
'src/hooks/index.ts',
'src/lib/index.ts',
'src/types/index.ts',
'src/utils/index.ts',
'src/UI/index.ts',
],
output: [
{
format: 'cjs',
dir: 'dist',
exports: 'auto',
preserveModules: true,
preserveModulesRoot: 'src',
sourcemap: true,
},
],
plugins: [
// Preferably set as first plugin.
peerDepsExternal(),
typescript({
tsconfig: './tsconfig.rollup.json',
}),
postcss({
extract: false,
modules: true,
use: ['sass'],
}),
],
};
export default options;
scripts/postinstall.sh
#!/usr/bin/env bash
set -e;
# skip postinstall if npm install for development
# rollup.config.js is not included in dist
if [ -f "rollup.config.js" ]; then
echo "skipping your package's postinstall routine.";
exit 0;
fi
echo 'Copying files from dist folder into root project folder...'
cp -r dist/* ./ && rm -rf dist
echo 'Postinstall done!'
package.json
"scripts": {
"postinstall": "./scripts/postinstall.sh",
},
这将编译所有文件并将其输出到 dist 文件夹。安装后脚本会将 dist 中的所有文件复制到根项目文件夹中。
注意*:当 运行 npm 在本地安装时,应该跳过安装后脚本。这是通过检查 rollup.config.js 是否存在来完成的。
这是可能的,但需要一些额外的步骤。上面提到过,这是Material-UI.
采取的做法
诀窍是发布一个精选的 dist
文件夹,而不是您的存储库的根文件夹。
建筑
首先,让我们明确一点,您的库是使用 CommonJS 还是 ESM 构建的并不重要。这是关于模块分辨率。
我们假设项目名为 my-package
。
现在大多数项目,在我们构建 src/
到 dist/
之后都会有
my-package
package.json
src/
index.js
dist/
index.js
并在 package.json
"main": "dist/index.js"
或 esm
"module": "dist/index.js"
发布
大多数项目只是添加 .npmignore
并发布项目的根目录,因此安装后项目最终在 node_modules
中,如下所示:
node_modules
my-package/
package.json
dist/
index.js
正在解决
安装后,考虑导入:
import myProject from "my-project";
模块解析器将执行此操作(大大简化,因为 full algorithm 与此处无关):
- 转到
node_modules
- 找到
my-project
- 加载
package.json
- Return
main
或 module
中的文件
这会起作用,因为我们有
node_modules
my-package/
package.json
dist/
index.js
正在解析子路径
import something from "my-project/something";
分辨率算法将适用于
node_modules
my-project/
somthing.js
还有
node_modules
my-project/
something/
index.js
并与
node_modules
my-project/
something/
package.json
在后一种情况下,它将再次查看 main
或 module
。
但是我们有:
node_modules
my-package/
package.json
dist/
index.js
绝招
诀窍是,不要使用 dist
文件夹发布项目根目录,而是“frank”dist
文件夹并使用 npm publish dist
发布 dist
文件夹相反。
Frank(如 frank a letter)表示您需要在 dist
文件夹中创建一个 package.json
;添加 README.md
LICENSE
等
可以找到关于如何完成此操作的一个相当简短的示例 here。
所以,鉴于我们在构建之后有:
node_modules
my-package/
package.json
dist/
index.js
something.js
发布后我们得到
node_modules
my-project/
package.json
index.js
something.js
其中 package.json
是精选的。
我有一个包含多个文件夹的打字稿库。每个文件夹都包含一个 index.ts 文件,该文件导出一些业务逻辑。我正在尝试将其与汇总捆绑在一起以在呼叫站点上实现此行为:
import { Button, ButtonProps } from 'my-lib/button'
import { Input, Textarea } from 'my-lib/input'
import { Row, Column } from 'my-lib/grid'
这是目录结构:
我在 src/
下有一个主要 index.ts
,其中包含:
export * from './button';
export * from './input';
export * from './grid';
有了这个风格,我可以做到:
import { Button, Input, InputProps, Row, Column } from 'my-lib'
但我不想要这个。我想通过它们的命名空间访问每个模块。如果我从 index.ts
文件中删除导出,我所能做的就是:
import { Button } from 'my-lib/dist/button'
这是我以前没见过的。添加 dist/
到 import 语句意味着我通过相对路径访问模块。我想要 my-lib/Button
.
我正在使用汇总。我尝试使用 alias
插件但没有用。下面是我的汇总配置:
const customResolver = resolve({
extensions: ['ts'],
});
export default {
input: `src/index.ts`,
output: [
{
file: pkg.main,
format: 'cjs',
sourcemap: true,
// plugins: [terser()],
},
{
file: pkg.module,
format: 'es',
sourcemap: true,
plugins: [terser()],
},
],
// Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash')
external: [],
watch: {
include: 'src/**',
},
plugins: [
// Allow json resolution
json(),
// Compile TypeScript files
typescript({ useTsconfigDeclarationDir: true }),
// Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
commonjs(),
// Allow node_modules resolution, so you can use 'external' to control
// which external modules to include in the bundle
// https://github.com/rollup/rollup-plugin-node-resolve#usage
resolve(),
// Resolve source maps to the original source
sourceMaps(),
alias({
entries: [
{ find: 'my-lib/button', replacement: './dist/button' },
{ find: 'my-lib/input', replacement: './dist/input' },
{ find: 'my-lib/grid', replacement: './dist/grid' },
],
customResolver,
}),
],
};
这是 tsconfig
文件:
{
"compilerOptions": {
"target": "es5",
"module": "ES6",
"lib": ["ES2017", "ES7", "ES6", "DOM"],
"declaration": true,
"declarationDir": "dist",
"outDir": "dist",
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowJs": false,
"moduleResolution": "node",
"resolveJsonModule": true,
"baseUrl": "./src",
"paths": {
"my-lib/button": ["./src/button"],
"my-lib/input": ["./src/input"],
"my-lib/grid": ["./src/grid"]
}
},
"exclude": ["node_modules", "dist", "**/*.test.ts"],
"include": ["src/**/*.ts"]
}
我不知道如何使用汇总实现与 lodash/xxx
或 material-ui/yyy
相同的结构。
人们建议使用别名或命名导出,但我做不到。
最接近我的问题的是下面的问题:
我想实现同样的事情,但使用 typescript
和 rollup
。
我想我漏掉了什么,谢谢。
首先,两者的唯一区别
import { Button } from 'my-lib/dist/button'
和
import { Button } from 'my-lib/button'
只是多了一层目录。
曾经说过,在 tsconfig.json
文件中包含 "outDir": "dist",
之前,您需要将 dist/
添加到 import
语句中。
确实,您举的两个库都随根目录中的文件一起分发:lodash directly has js
files in the root, while material-ui 在其 tsconfig.json
文件中没有 outDir
选项(这意味着写入输出文件到根目录)。
希望对您有所帮助。
经过多次试验和错误后,我能够通过输入列表、使用 preserveModules and preserveModulesRoot 选项和一个简单的安装后脚本来实现此功能。
这是我的 rollup.config.js
const options = {
input: [
'src/index.ts',
'src/api/index.ts',
'src/components/index.ts',
'src/contexts/index.ts',
'src/hooks/index.ts',
'src/lib/index.ts',
'src/types/index.ts',
'src/utils/index.ts',
'src/UI/index.ts',
],
output: [
{
format: 'cjs',
dir: 'dist',
exports: 'auto',
preserveModules: true,
preserveModulesRoot: 'src',
sourcemap: true,
},
],
plugins: [
// Preferably set as first plugin.
peerDepsExternal(),
typescript({
tsconfig: './tsconfig.rollup.json',
}),
postcss({
extract: false,
modules: true,
use: ['sass'],
}),
],
};
export default options;
scripts/postinstall.sh
#!/usr/bin/env bash
set -e;
# skip postinstall if npm install for development
# rollup.config.js is not included in dist
if [ -f "rollup.config.js" ]; then
echo "skipping your package's postinstall routine.";
exit 0;
fi
echo 'Copying files from dist folder into root project folder...'
cp -r dist/* ./ && rm -rf dist
echo 'Postinstall done!'
package.json
"scripts": {
"postinstall": "./scripts/postinstall.sh",
},
这将编译所有文件并将其输出到 dist 文件夹。安装后脚本会将 dist 中的所有文件复制到根项目文件夹中。
注意*:当 运行 npm 在本地安装时,应该跳过安装后脚本。这是通过检查 rollup.config.js 是否存在来完成的。
这是可能的,但需要一些额外的步骤。上面提到过,这是Material-UI.
采取的做法诀窍是发布一个精选的 dist
文件夹,而不是您的存储库的根文件夹。
建筑
首先,让我们明确一点,您的库是使用 CommonJS 还是 ESM 构建的并不重要。这是关于模块分辨率。
我们假设项目名为 my-package
。
现在大多数项目,在我们构建 src/
到 dist/
之后都会有
my-package
package.json
src/
index.js
dist/
index.js
并在 package.json
"main": "dist/index.js"
或 esm
"module": "dist/index.js"
发布
大多数项目只是添加 .npmignore
并发布项目的根目录,因此安装后项目最终在 node_modules
中,如下所示:
node_modules
my-package/
package.json
dist/
index.js
正在解决
安装后,考虑导入:
import myProject from "my-project";
模块解析器将执行此操作(大大简化,因为 full algorithm 与此处无关):
- 转到
node_modules
- 找到
my-project
- 加载
package.json
- Return
main
或module
中的文件
这会起作用,因为我们有
node_modules
my-package/
package.json
dist/
index.js
正在解析子路径
import something from "my-project/something";
分辨率算法将适用于
node_modules
my-project/
somthing.js
还有
node_modules
my-project/
something/
index.js
并与
node_modules
my-project/
something/
package.json
在后一种情况下,它将再次查看 main
或 module
。
但是我们有:
node_modules
my-package/
package.json
dist/
index.js
绝招
诀窍是,不要使用 dist
文件夹发布项目根目录,而是“frank”dist
文件夹并使用 npm publish dist
发布 dist
文件夹相反。
Frank(如 frank a letter)表示您需要在 dist
文件夹中创建一个 package.json
;添加 README.md
LICENSE
等
可以找到关于如何完成此操作的一个相当简短的示例 here。
所以,鉴于我们在构建之后有:
node_modules
my-package/
package.json
dist/
index.js
something.js
发布后我们得到
node_modules
my-project/
package.json
index.js
something.js
其中 package.json
是精选的。