带有 Expo 和 Typescript 的 NPM 工作区
NPM workspaces with Expo and Typescript
我正在尝试在 Typescript Expo 项目中使用 NPM 7 工作区。
现在我想保留正常的 Expo 结构(使用根 App.tsx
文件),但我想在工作区中隔离部分代码。
我在工作区内编译 TS 代码时遇到问题。我尝试了很多东西来配置 TS and/or Webpack 配置但没有成功。所以这是重现它的最小文件结构:
package.json
tsconfig.json
App.tsx
/packages
/core
index.ts
package.json
这里是根的相关部分./package.json
{
"main": "node_modules/expo/AppEntry.js",
"workspaces": [
"packages/*"
],
"scripts": {...},
"dependencies": {...},
"devDependencies": {...},
"private": true
}
./tsconfig.json
是最低限度
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
}
}
./packages/core/package.json
也很简单
{
"name": "core",
"private": true
}
而 ./packages/core/index.ts
只是为这个例子导出一个 log()
函数
export function log(s: string) {
console.log(s)
}
最后,在./App.tsx
中,只是导入函数并尝试调用它
import { log } from 'core'
log('hello')
//...
它不编译
当我尝试为 web 构建时(例如 expo build:web
),出现以下错误
✖ Expo Webpack
Compiled with some errors in 1.62s
Failed to compile.
[path]/node_modules/core/index.ts 1:21
Module parse failed: Unexpected token (1:21)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export function log(s: string) {
| console.log(s)
| }
我并不感到惊讶,因为 /node_modules
目录是自愿排除的。
所以我的问题是我需要做什么才能编译工作区代码?我希望它能即时运行(即:未预编译),就像它是我项目中的一些常规文件一样。完全可行吗?
一些修复失败的尝试
我主要尝试调整 tsconfig 以使其正常工作(尽管我想知道它是否改变了什么)
#1
我尝试在 ./tsconfig.json
中添加 "include": ["./node_modules/core"],
。 没有效果(同样的错误)。
#2
我尝试使用复合选项创建以下 /packages/core/tsconfig.json
:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"composite": true
}
}
并在根目录中引用它 tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
},
"references": [{ "path": "./node_modules/core" }]
// or even with:
"references": [{ "path": "./packages/core" }]
}
没有效果(同样的错误)。
非常感谢
我想出了一个我不是很满意但至少它有效的解决方案。它实际上非常简单,我只是配置 Webpack 来编译我的 packages/*
(作为 node_modules
.
中的符号链接
首先我安装了:
$ npm i -D ts-loader@8 webpack@4.430
这里的版本很重要,要与 Expo 41 使用的 webpack 版本保持一致。
我还将我的包名称(在 /packages/core/package.json
中)重命名为 @workspace/core
这样我所有的自定义包都在 node_modules/@workspace
目录中。
它也会使我们的配置更简单。
运行 $ expo customize:web
是自定义 webpack 配置所必需的。它将产生 webpack.config.js
.
可自定义如下:
const createExpoWebpackConfigAsync = require('@expo/webpack-config')
module.exports = async function (env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv)
config.module.rules = [
{
// this is why I renamed my packages with the @workspaces prefix.
test: /node_modules\/@workspaces\/(.*)\.ts$/,
use: [
{
loader: 'ts-loader',
// force ts-loader to compile in node_modules
options: { allowTsInNodeModules: true },
},
],
},
...config.module.rules,
]
return config
}
如果有更清洁的解决方案,我不会感到惊讶。但现在我会坚持下去
我正在尝试在 Typescript Expo 项目中使用 NPM 7 工作区。
现在我想保留正常的 Expo 结构(使用根 App.tsx
文件),但我想在工作区中隔离部分代码。
我在工作区内编译 TS 代码时遇到问题。我尝试了很多东西来配置 TS and/or Webpack 配置但没有成功。所以这是重现它的最小文件结构:
package.json
tsconfig.json
App.tsx
/packages
/core
index.ts
package.json
这里是根的相关部分./package.json
{
"main": "node_modules/expo/AppEntry.js",
"workspaces": [
"packages/*"
],
"scripts": {...},
"dependencies": {...},
"devDependencies": {...},
"private": true
}
./tsconfig.json
是最低限度
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
}
}
./packages/core/package.json
也很简单
{
"name": "core",
"private": true
}
而 ./packages/core/index.ts
只是为这个例子导出一个 log()
函数
export function log(s: string) {
console.log(s)
}
最后,在./App.tsx
中,只是导入函数并尝试调用它
import { log } from 'core'
log('hello')
//...
它不编译
当我尝试为 web 构建时(例如 expo build:web
),出现以下错误
✖ Expo Webpack
Compiled with some errors in 1.62s
Failed to compile.
[path]/node_modules/core/index.ts 1:21
Module parse failed: Unexpected token (1:21)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export function log(s: string) {
| console.log(s)
| }
我并不感到惊讶,因为 /node_modules
目录是自愿排除的。
所以我的问题是我需要做什么才能编译工作区代码?我希望它能即时运行(即:未预编译),就像它是我项目中的一些常规文件一样。完全可行吗?
一些修复失败的尝试
我主要尝试调整 tsconfig 以使其正常工作(尽管我想知道它是否改变了什么)
#1
我尝试在 ./tsconfig.json
中添加 "include": ["./node_modules/core"],
。 没有效果(同样的错误)。
#2
我尝试使用复合选项创建以下 /packages/core/tsconfig.json
:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"composite": true
}
}
并在根目录中引用它 tsconfig.json
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
},
"references": [{ "path": "./node_modules/core" }]
// or even with:
"references": [{ "path": "./packages/core" }]
}
没有效果(同样的错误)。
非常感谢
我想出了一个我不是很满意但至少它有效的解决方案。它实际上非常简单,我只是配置 Webpack 来编译我的 packages/*
(作为 node_modules
.
首先我安装了:
$ npm i -D ts-loader@8 webpack@4.430
这里的版本很重要,要与 Expo 41 使用的 webpack 版本保持一致。
我还将我的包名称(在 /packages/core/package.json
中)重命名为 @workspace/core
这样我所有的自定义包都在 node_modules/@workspace
目录中。
它也会使我们的配置更简单。
运行 $ expo customize:web
是自定义 webpack 配置所必需的。它将产生 webpack.config.js
.
可自定义如下:
const createExpoWebpackConfigAsync = require('@expo/webpack-config')
module.exports = async function (env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv)
config.module.rules = [
{
// this is why I renamed my packages with the @workspaces prefix.
test: /node_modules\/@workspaces\/(.*)\.ts$/,
use: [
{
loader: 'ts-loader',
// force ts-loader to compile in node_modules
options: { allowTsInNodeModules: true },
},
],
},
...config.module.rules,
]
return config
}
如果有更清洁的解决方案,我不会感到惊讶。但现在我会坚持下去