راه اندازی Subpath Import Aliases در پروژه TypeScript

Summarize this content to 400 words in Persian Lang TL; DR استفاده از شرایط سفارشی
یک روز تصمیم گرفتم نام مستعار مسیر مدرن را در پروژه TypeScript خود بگنجانم. من انتظار نداشتم که چنین سفر چالش برانگیزی باشد! شما می توانید جزئیات را بخوانید ⏬
محتوا
مقدمه
پروژه نمونه
تلاش شماره 1: Node.js Docs را دنبال کنید
تلاش شماره 2: استفاده کنید dist به جای src
تلاش شماره 3: تنظیم کنید rootDir و outDir
تلاش شماره 4: اشاره به dist/src
تلاش شماره 5: شرایط سفارشی برای نجات
پیکربندی TypeScript را به روز کنید
پیکربندی Vitest را به روز کنید
ابزارهای دیگر
خلاصه
مقدمه
وارد کردن مسیرهای فرعی یک ویژگی بومی در Node.js است که امکان تعریف نام مستعار برای مسیرهای داخلی در یک پایگاه کد را فراهم می کند.
مثلا به جای نوشتن:
import { foo } from ‘../../../utils.js’;
شما می توانید یک وارد کردن مسیر فرعی را برای ساده کردن این کار به صورت زیر تنظیم کنید:
import { foo } from ‘#utils.js’;
دو فایده اصلی:
خواندن راحت تر
پس از جابجایی فایل ها هیچ تفاوت اضافی وجود ندارد
در تایپ اسکریپت، روش قدیمی تری برای تنظیم نام مستعار از طریق گزینه مسیرها وجود دارد. اگرچه برای خود TypeScript خوب کار می کند، اما مشکل اینجاست که Node.js از این پیکربندی آگاه نیست. برای اجرای کدهای کامپایل شده (tsconfig-paths، tsc-alias) باید از بسته های شخص ثالث استفاده کنید.
خبر خوب این است که از نسخه 4.8 TypeScript پشتیبانی برای واردات subpath اضافه شده است. در حالی که مفهوم ساده به نظر می رسد، ادغام واردات subpath در پروژه آزمایشی من مشکل بود. من تمام مسائل را مرحله به مرحله مرور می کنم و راه حل نهایی را به اشتراک می گذارم. بیایید شروع کنیم.
پروژه نمونه
ساختار پروژه زیر را تصور کنید:
my-project
├── src
│ ├── index.ts
│ └── utils.ts
├── test
│ └── index.spec.ts
├── package.json
├── tsconfig.build.json
├── tsconfig.json
└── vitest.config.mts
این یک تنظیم نسبتا معمولی است:
src و test به ترتیب شامل کد منبع و تست واحد است
tsconfig.json برای بررسی نوع کل پروژه
tsconfig.build.json برای کامپایل کد منبع از src به dist دایرکتوری
vitest.config.mts برای اجرای تست های واحد با vitest
در ابتدا، این پروژه از واردات فرعی استفاده نمی کند. src/index.ts از مسیر نسبی برای وارد کردن ثابت از Utils استفاده می کند:
// src/index.ts
import { foo } from ‘./utils.js’;
console.log(foo);
// src/utils.ts
export const foo = 42;
در test دایرکتوری همچنین وارد کردن utils توسط مسیر نسبی وجود دارد:
// test/index.spec.ts
import { foo } from ‘../src/utils.js’;
test(‘foo is 42’, () => {
expect(foo).toBe(42);
});
چند اسکریپت npm وجود دارد package.json، که در حالت اولیه پروژه با موفقیت اجرا شد:
“scripts”: {
“tsc”: “tsc”,
“test”: “vitest run”,
“build”: “tsc -p tsconfig.build.json”,
“start”: “node dist/index.js”
}
npm run tsc – کل پروژه را تایپ کنید
npm run test – تست ها را با کد واقعی در داخل اجرا کنید src
npm run build – کامپایل کد از src به dist دایرکتوری
npm start – اجرای پروژه از dist دایرکتوری
من از این دستورات به عنوان یک چک لیست استفاده خواهم کرد تا مطمئن شوم همه چیز بعد از راه اندازی imports subpath کار می کند.
همچنین، من در VSCode آن را بررسی خواهم کرد CMD / CTRL + click در utils import به محتویات فایل هدایت می شود.
تلاش شماره 1: Node.js Docs را دنبال کنید
اولین قدم من دنبال کردن نمونههای مستندات Node.js بود. من اضافه کردم imports میدان به package.json و نام مستعار را برای src دایرکتوری
// package.json
{
“name”: “subpath-imports-typescript”,
+ “imports”: {
+ “#*”: “./src/*”
+ },
}
و از آن نام مستعار در استفاده کرد src/index.ts و test/index.spec.ts:
// src/index.ts
– import { foo } from ‘./utils’;
+ import { foo } from ‘#utils.js’;
// test/index.spec.ts
– import { foo } from ‘../src/utils.js’;
+ import { foo } from ‘#utils.js’;
پس از انجام این تغییرات، تمام دستورات به جز دستور کار کردند npm start، که با خطای زیر ناموفق بود:
> node dist/index.js
node:internal/modules/cjs/loader:1110
throw e;
^
Error: Cannot find module ‘/projects/subpath-imports-typescript/src/utils.js’
مشکل به این دلیل رخ داد که Node.js به دنبال آن بود utils.js در src دایرکتوری به جای dist دایرکتوری از آنجایی که پروژه قرار است از dist دایرکتوری، Node.js نتوانست فایل مورد نیاز را پیدا کند.
تلاش شماره 2: استفاده کنید dist به جای src
برای رفع این مشکل، من را تنظیم کردم imports میدان در package.json برای اشاره به dist دایرکتوری به جای src:
{
“name”: “subpath-imports-typescript”,
“imports”: {
– “#*”: “./src/*”
+ “#*”: “./dist/*”
},
}
در ابتدا، به نظر می رسید که این تغییر موثر باشد. با این حال، یک بار من آن را حذف کردم dist دایرکتوری، همه چیز خراب شد! VSCode دیگر نمی تواند آن را پیدا کند #utils.js ماژول و TypeScript یک خطا نشان داد:
Cannot find module ‘#utils.js’ or its corresponding type declarations.
علت اصلی این بود که TypeScript و VSCode نمیتوانستند نام مستعار را حل کنند زیرا فایلهای موجود در dist دایرکتوری وجود ندارد
مشکل مرغ و تخم مرغ – فایل های منبع به فایل های کامپایل شده برای دریافت فایل های کامپایل شده ارجاع می دهند
برای رسیدگی به این مشکل، اسناد TypeScript توصیه می کند که تنظیم کنید rootDir و outDir گزینه ها در tsconfig.json.
تلاش شماره 3: تنظیم کنید rootDir و outDir
من اضافه کردم rootDir و outDir گزینه ها:
// tsconfig.json
{
“compilerOptions”: {
“target”: “es2021”,
“module”: “NodeNext”,
+ “rootDir”: “src”,
+ “outDir”: “dist”,
“noEmit”: true,
“skipLibCheck”: true
},
“include”: [“**/*.ts”]
}
ایده در اینجا به این صورت است: زمانی که TypeScript دایرکتوری های مبدا و مقصد فایل های کامپایل شده را می داند، می تواند نام مستعار وارداتی را مجدداً به محل مبدا نقشه برداری کند.
در مورد من، #utils.js ابتدا حل خواهد شد ./dist/utils.js و سپس دوباره به نقشه برداری می شود ./src/utils.ts.
با این حال، وقتی دویدم tsc، TypeScript خطای زیر را ایجاد کرد:
File ‘/xxx/subpath-imports-typescript/test/index.spec.ts’ is not under ‘rootDir’
‘/xxx/subpath-imports-typescript/src’. ‘rootDir’ is expected to contain all source files.
برای حل این مشکل، مجبور شدم آن را محدود کنم include گزینه ای به src/**/*.ts:
{
“compilerOptions”: {
“target”: “es2021”,
“module”: “NodeNext”,
“rootDir”: “src”,
“outDir”: “dist”,
“noEmit”: true,
“skipLibCheck”: true
},
– “include”: [“**/*.ts”]
+ “include”: [“src/**/*.ts”]
}
این تغییر ایجاد شد tsc کار کردن
جنبه منفی – اکنون پیکربندی TypeScript فقط برای اعمال می شود src دایرکتوری و فایل ها در test مستثنی هستند. VSCode دیگر نمی تواند کلیک روی آن را حل کند #utils.js واردات در test دایرکتوری، و vitest یک خطا می زند:
Error: Failed to load url #utils.js (resolved id: #utils.js) in /xxx/subpath-imports-typescript/test/index.spec.ts. Does the file exist?
اولین راه حل بالقوه اشاره بود rootDir به “.” به جای src برای پوشش کل پروژه:
{
“compilerOptions”: {
“target”: “es2021”,
“module”: “NodeNext”,
– “rootDir”: “src”,
+ “rootDir”: “.”,
“outDir”: “dist”,
“noEmit”: true,
“skipLibCheck”: true
},
– “include”: [“src/**/*.ts”]
+ “include”: [“**/*.ts”]
}
با این حال، این نیز کمکی نکرد. وقتی دویدم tsc، TypeScript هنوز شکایت می کند:
Cannot find module ‘#utils.js’ or its corresponding type declarations.
حالا دلیلش فرق می کرد. چه زمانی rootDir تنظیم شد “.”، TypeScript کل ساختار پروژه را در داخل تکرار کرد dist دایرکتوری، در نتیجه:
├── dist
│ ├── src
│ │ ├── index.js
│ │ └── utils.js
│ └── test
│ └── index.spec.js
اما imports میدان در package.json اشاره کرد dist/utils.js، نه dist/src/utils.js.
تلاش شماره 4: اشاره به dist/src
باشه من تنظیم کردم imports میدانی برای اشاره dist/src:
{
“imports”: {
– “#*”: “./dist/*”
+ “#*”: “./dist/src/*”
}
}
این تغییر اجازه داد tsc به درستی کار کند، و VSCode اکنون می تواند به آن پیمایش کند utils.js در src.
با این حال، زمانی که من سعی کردم پروژه را با npm run build، من یک خطا دارم:
Cannot find module ‘#utils.js’ or its corresponding type declarations.
موضوع این بود که tsconfig.build.json هنوز داشت rootDir اشاره کرد src. من آپدیت کردم rootDir به “.” در tsconfig.build.ts همچنین:
// tsconfig.build.ts
{
“extends”: “./tsconfig.json”,
“compilerOptions”: {
– “rootDir”: “src”,
+ “rootDir”: “.”,
“outDir”: “dist”,
“noEmit”: false,
},
“include”: [“src”]
}
اکنون TypeScript خوشحال است و من می توانم پروژه را کامپایل و بسازم! 🎉
بله، تودرتوی اضافی را در داخل معرفی کرد dist دایرکتوری قبلا، dist دایرکتوری به شکل زیر بود:
├── dist
│ ├── index.js
│ └── utils.js
و حالا با تو در تو src:
├── dist
│ ├── src
│ │ ├── index.js
│ │ └── utils.js
چیز مهمی نیست، من حاضرم آن را بپذیرم!
اما.. تست ها هنوز اجرا نمی شوند 🤯
npm run test یک خطا ایجاد می کند:
Failed to load url #utils.js (resolved id: #utils.js) in /xxx/subpath-imports-typescript/test/index.spec.ts. Does the file exist?
به این دلیل است که فقط TypeScript از آن آگاه است rootDir و outDir نقشه برداری مجدد همه ابزارهای دیگر، مانند Vitest، نقشه برداری را تشخیص ندادند، که منجر به خطاهای زمان اجرا در هنگام تلاش برای حل کردن #utils.js از test دایرکتوری
گیر کرده بودم. من قصد داشتم از واردات مرموز زیرمسیر صرف نظر کنم و به نام مستعار مسیر TypeScript برگردم. اما پس از مطالعه مستندات بیشتر و مشکلات GitHub، راه حلی پیدا کردم!
تلاش شماره 5: شرایط سفارشی برای نجات
طبق اسناد Node.js، میتوانید از طریق شیء، نام مستعار وارداتی را به چندین مکان نگاشت کنید:
“imports”: {
“#*”: {
“condition-a”: “./location-a/*”,
“condition-b”: “./location-b/*”
}
}
کلیدهای آن شیء را شرایط می گویند. شرایط داخلی مانند وجود دارد default، require یا import، اما همچنین می تواند هر رشته سفارشی که توسط کاربر تعریف شده باشد وجود داشته باشد.
من اصلاح کردم imports میدان در package.json برای گنجاندن یک شرط سفارشی my-package-dev با اشاره به src و نگهداری کرد default شرط اشاره به dist:
“imports”: {
– “#*”: “./dist/src/*”
+ “#*”: {
+ “my-package-dev”: “./src/*”,
+ “default”: “./dist/*”
+ }
}
بنابراین، دو راه برای حل وجود دارد # واردات:
my-package-dev – به Node.js می گوید که مسیرها را از src دایرکتوری زمانی که شرط فعال است (در طول توسعه)
default – گزینه بازگشتی برای حل مسیرها از dist دایرکتوری زمانی که شرایط خاصی ارائه نشده باشد
توجه: من عمداً وضعیتم را نام بردم my-package-dev، نه فقط dev. این برای نویسندگان کتابخانه مهم است. اگر مصرف کنندگان شما پروژه خود را با dev شرایط، بسته شما در node_modules آن شرط را نیز در نظر می گیرد و سعی می کند فایل ها را از src! اگر برنامه کاربران نهایی را توسعه می دهید، می توانید استفاده کنید dev یا development به عنوان نام شرط
پیکربندی TypeScript را به روز کنید
اکنون باید به TypeScript در مورد شرایط سفارشی خود اطلاع دهم. خوشبختانه، tsconfig.json یک گزینه customConditions برای آن فراهم می کند. تمام تغییرات انجام شده در مراحل قبلی را برگردانده و اضافه کرده ام customConditions زمینه:
// tsconfig.json
“compilerOptions”: {
“target”: “es2021”,
“module”: “NodeNext”,
+ “customConditions”: [“my-package-dev”],
“noEmit”: true,
“skipLibCheck”: true,
}
با این تنظیمات، TypeScript به درستی وارد کردن مسیرهای فرعی را از مسیر حل می کند src دایرکتوری حتی بدون rootDir و outDir گزینه ها VSCode نیز به درستی پیمایش می کند utils.ts مکان
پیکربندی Vitest را به روز کنید
Vitest همچنین از ارائه شرایط سفارشی پشتیبانی می کند. من تنظیم کرده ام resolve.conditions در vitest.config.mts:
import { defineConfig } from ‘vitest/config’;
export default defineConfig({
+ resolve: {
+ conditions: [‘my-package-dev’],
+ },
});
پس از این تغییر، vitest در حال حل و فصل فایلها بود src دایرکتوری که از بررسی کد واقعی در طول آزمایش اطمینان حاصل می کند:
ابزارهای دیگر
برای سایر ابزارها، باید اسناد آنها را در مورد پشتیبانی از شرایط سفارشی بررسی کنید. من سعی کردم پروژه ام را با tsx اجرا کنم. از آنجایی که از تمام پرچمهای Node.js پشتیبانی میکند، من به تازگی شرایط سفارشی را از طریق آن ارائه کردهام -C پرچم:
$ npx tsx -C my-package-dev src/index.ts
42
کار می کند.
من می توانم یک مرور کلی از پشتیبانی واردات subpath در ابزارها و IDE های مختلف را توصیه کنم.
خلاصه
این یک سفر چالش برانگیز برای راه اندازی واردات فرعی بود. به خصوص هنگام اطمینان از سازگاری در جریان توسعه، ابزارهای آزمایش، پشتیبانی IDE و اجرای تولید.
با این حال، نتیجه موفقیت آمیز است و راه اندازی نهایی چیز خیلی پیچیده ای نیست. من مطمئن هستم که وارد کردن مسیرهای فرعی در نهایت به یک روش پیشفرض برای نام مستعار در پروژههای Node.js تبدیل خواهد شد. امیدوارم این مقاله در وقت شما صرفه جویی کند!
من یک نمونه کار نهایی را در GitHub منتشر کرده ام، شما می توانید آن را بررسی کنید. با تشکر برای خواندن و کد نویسی خوشحال! ❤️
TL; DR استفاده از شرایط سفارشی
یک روز تصمیم گرفتم نام مستعار مسیر مدرن را در پروژه TypeScript خود بگنجانم. من انتظار نداشتم که چنین سفر چالش برانگیزی باشد! شما می توانید جزئیات را بخوانید ⏬
محتوا
- مقدمه
- پروژه نمونه
- تلاش شماره 1: Node.js Docs را دنبال کنید
- تلاش شماره 2: استفاده کنید
dist
به جایsrc
- تلاش شماره 3: تنظیم کنید
rootDir
وoutDir
- تلاش شماره 4: اشاره به
dist/src
-
تلاش شماره 5: شرایط سفارشی برای نجات
- پیکربندی TypeScript را به روز کنید
- پیکربندی Vitest را به روز کنید
- ابزارهای دیگر
- خلاصه
مقدمه
وارد کردن مسیرهای فرعی یک ویژگی بومی در Node.js است که امکان تعریف نام مستعار برای مسیرهای داخلی در یک پایگاه کد را فراهم می کند.
مثلا به جای نوشتن:
import { foo } from '../../../utils.js';
شما می توانید یک وارد کردن مسیر فرعی را برای ساده کردن این کار به صورت زیر تنظیم کنید:
import { foo } from '#utils.js';
دو فایده اصلی:
- خواندن راحت تر
- پس از جابجایی فایل ها هیچ تفاوت اضافی وجود ندارد
در تایپ اسکریپت، روش قدیمی تری برای تنظیم نام مستعار از طریق گزینه مسیرها وجود دارد. اگرچه برای خود TypeScript خوب کار می کند، اما مشکل اینجاست که Node.js از این پیکربندی آگاه نیست. برای اجرای کدهای کامپایل شده (tsconfig-paths، tsc-alias) باید از بسته های شخص ثالث استفاده کنید.
خبر خوب این است که از نسخه 4.8 TypeScript پشتیبانی برای واردات subpath اضافه شده است. در حالی که مفهوم ساده به نظر می رسد، ادغام واردات subpath در پروژه آزمایشی من مشکل بود. من تمام مسائل را مرحله به مرحله مرور می کنم و راه حل نهایی را به اشتراک می گذارم. بیایید شروع کنیم.
پروژه نمونه
ساختار پروژه زیر را تصور کنید:
my-project
├── src
│ ├── index.ts
│ └── utils.ts
├── test
│ └── index.spec.ts
├── package.json
├── tsconfig.build.json
├── tsconfig.json
└── vitest.config.mts
این یک تنظیم نسبتا معمولی است:
-
src
وtest
به ترتیب شامل کد منبع و تست واحد است -
tsconfig.json
برای بررسی نوع کل پروژه -
tsconfig.build.json
برای کامپایل کد منبع ازsrc
بهdist
دایرکتوری -
vitest.config.mts
برای اجرای تست های واحد با vitest
در ابتدا، این پروژه از واردات فرعی استفاده نمی کند. src/index.ts
از مسیر نسبی برای وارد کردن ثابت از Utils استفاده می کند:
// src/index.ts
import { foo } from './utils.js';
console.log(foo);
// src/utils.ts
export const foo = 42;
در test
دایرکتوری همچنین وارد کردن utils توسط مسیر نسبی وجود دارد:
// test/index.spec.ts
import { foo } from '../src/utils.js';
test('foo is 42', () => {
expect(foo).toBe(42);
});
چند اسکریپت npm وجود دارد package.json
، که در حالت اولیه پروژه با موفقیت اجرا شد:
"scripts": {
"tsc": "tsc",
"test": "vitest run",
"build": "tsc -p tsconfig.build.json",
"start": "node dist/index.js"
}
-
npm run tsc
– کل پروژه را تایپ کنید -
npm run test
– تست ها را با کد واقعی در داخل اجرا کنیدsrc
-
npm run build
– کامپایل کد ازsrc
بهdist
دایرکتوری -
npm start
– اجرای پروژه ازdist
دایرکتوری
من از این دستورات به عنوان یک چک لیست استفاده خواهم کرد تا مطمئن شوم همه چیز بعد از راه اندازی imports subpath کار می کند.
همچنین، من در VSCode آن را بررسی خواهم کرد CMD / CTRL + click
در utils import به محتویات فایل هدایت می شود.
تلاش شماره 1: Node.js Docs را دنبال کنید
اولین قدم من دنبال کردن نمونههای مستندات Node.js بود. من اضافه کردم imports
میدان به package.json
و نام مستعار را برای src
دایرکتوری
// package.json
{
"name": "subpath-imports-typescript",
+ "imports": {
+ "#*": "./src/*"
+ },
}
و از آن نام مستعار در استفاده کرد src/index.ts
و test/index.spec.ts
:
// src/index.ts
- import { foo } from './utils';
+ import { foo } from '#utils.js';
// test/index.spec.ts
- import { foo } from '../src/utils.js';
+ import { foo } from '#utils.js';
پس از انجام این تغییرات، تمام دستورات به جز دستور کار کردند npm start
، که با خطای زیر ناموفق بود:
> node dist/index.js
node:internal/modules/cjs/loader:1110
throw e;
^
Error: Cannot find module '/projects/subpath-imports-typescript/src/utils.js'
مشکل به این دلیل رخ داد که Node.js به دنبال آن بود utils.js
در src
دایرکتوری به جای dist
دایرکتوری از آنجایی که پروژه قرار است از dist
دایرکتوری، Node.js نتوانست فایل مورد نیاز را پیدا کند.
تلاش شماره 2: استفاده کنید dist
به جای src
برای رفع این مشکل، من را تنظیم کردم imports
میدان در package.json
برای اشاره به dist
دایرکتوری به جای src
:
{
"name": "subpath-imports-typescript",
"imports": {
- "#*": "./src/*"
+ "#*": "./dist/*"
},
}
در ابتدا، به نظر می رسید که این تغییر موثر باشد. با این حال، یک بار من آن را حذف کردم dist
دایرکتوری، همه چیز خراب شد! VSCode دیگر نمی تواند آن را پیدا کند #utils.js
ماژول و TypeScript یک خطا نشان داد:
Cannot find module '#utils.js' or its corresponding type declarations.
علت اصلی این بود که TypeScript و VSCode نمیتوانستند نام مستعار را حل کنند زیرا فایلهای موجود در dist
دایرکتوری وجود ندارد
مشکل مرغ و تخم مرغ – فایل های منبع به فایل های کامپایل شده برای دریافت فایل های کامپایل شده ارجاع می دهند
برای رسیدگی به این مشکل، اسناد TypeScript توصیه می کند که تنظیم کنید rootDir
و outDir
گزینه ها در tsconfig.json
.
تلاش شماره 3: تنظیم کنید rootDir
و outDir
من اضافه کردم rootDir
و outDir
گزینه ها:
// tsconfig.json
{
"compilerOptions": {
"target": "es2021",
"module": "NodeNext",
+ "rootDir": "src",
+ "outDir": "dist",
"noEmit": true,
"skipLibCheck": true
},
"include": ["**/*.ts"]
}
ایده در اینجا به این صورت است: زمانی که TypeScript دایرکتوری های مبدا و مقصد فایل های کامپایل شده را می داند، می تواند نام مستعار وارداتی را مجدداً به محل مبدا نقشه برداری کند.
در مورد من، #utils.js
ابتدا حل خواهد شد ./dist/utils.js
و سپس دوباره به نقشه برداری می شود ./src/utils.ts
.
با این حال، وقتی دویدم tsc
، TypeScript خطای زیر را ایجاد کرد:
File '/xxx/subpath-imports-typescript/test/index.spec.ts' is not under 'rootDir'
'/xxx/subpath-imports-typescript/src'. 'rootDir' is expected to contain all source files.
برای حل این مشکل، مجبور شدم آن را محدود کنم include
گزینه ای به src/**/*.ts
:
{
"compilerOptions": {
"target": "es2021",
"module": "NodeNext",
"rootDir": "src",
"outDir": "dist",
"noEmit": true,
"skipLibCheck": true
},
- "include": ["**/*.ts"]
+ "include": ["src/**/*.ts"]
}
این تغییر ایجاد شد tsc
کار کردن
جنبه منفی – اکنون پیکربندی TypeScript فقط برای اعمال می شود src
دایرکتوری و فایل ها در test
مستثنی هستند. VSCode دیگر نمی تواند کلیک روی آن را حل کند #utils.js
واردات در test
دایرکتوری، و vitest یک خطا می زند:
Error: Failed to load url #utils.js (resolved id: #utils.js) in /xxx/subpath-imports-typescript/test/index.spec.ts. Does the file exist?
اولین راه حل بالقوه اشاره بود rootDir
به "."
به جای src
برای پوشش کل پروژه:
{
"compilerOptions": {
"target": "es2021",
"module": "NodeNext",
- "rootDir": "src",
+ "rootDir": ".",
"outDir": "dist",
"noEmit": true,
"skipLibCheck": true
},
- "include": ["src/**/*.ts"]
+ "include": ["**/*.ts"]
}
با این حال، این نیز کمکی نکرد. وقتی دویدم tsc
، TypeScript هنوز شکایت می کند:
Cannot find module '#utils.js' or its corresponding type declarations.
حالا دلیلش فرق می کرد. چه زمانی rootDir
تنظیم شد "."
، TypeScript کل ساختار پروژه را در داخل تکرار کرد dist
دایرکتوری، در نتیجه:
├── dist
│ ├── src
│ │ ├── index.js
│ │ └── utils.js
│ └── test
│ └── index.spec.js
اما imports
میدان در package.json
اشاره کرد dist/utils.js
، نه dist/src/utils.js
.
تلاش شماره 4: اشاره به dist/src
باشه من تنظیم کردم imports
میدانی برای اشاره dist/src
:
{
"imports": {
- "#*": "./dist/*"
+ "#*": "./dist/src/*"
}
}
این تغییر اجازه داد tsc
به درستی کار کند، و VSCode اکنون می تواند به آن پیمایش کند utils.js
در src
.
با این حال، زمانی که من سعی کردم پروژه را با npm run build
، من یک خطا دارم:
Cannot find module '#utils.js' or its corresponding type declarations.
موضوع این بود که tsconfig.build.json
هنوز داشت rootDir
اشاره کرد src
. من آپدیت کردم rootDir
به "."
در tsconfig.build.ts
همچنین:
// tsconfig.build.ts
{
"extends": "./tsconfig.json",
"compilerOptions": {
- "rootDir": "src",
+ "rootDir": ".",
"outDir": "dist",
"noEmit": false,
},
"include": ["src"]
}
اکنون TypeScript خوشحال است و من می توانم پروژه را کامپایل و بسازم! 🎉
بله، تودرتوی اضافی را در داخل معرفی کرد dist
دایرکتوری قبلا، dist
دایرکتوری به شکل زیر بود:
├── dist
│ ├── index.js
│ └── utils.js
و حالا با تو در تو src
:
├── dist
│ ├── src
│ │ ├── index.js
│ │ └── utils.js
چیز مهمی نیست، من حاضرم آن را بپذیرم!
اما.. تست ها هنوز اجرا نمی شوند 🤯
npm run test
یک خطا ایجاد می کند:
Failed to load url #utils.js (resolved id: #utils.js) in /xxx/subpath-imports-typescript/test/index.spec.ts. Does the file exist?
به این دلیل است که فقط TypeScript از آن آگاه است rootDir
و outDir
نقشه برداری مجدد همه ابزارهای دیگر، مانند Vitest، نقشه برداری را تشخیص ندادند، که منجر به خطاهای زمان اجرا در هنگام تلاش برای حل کردن #utils.js
از test
دایرکتوری
گیر کرده بودم. من قصد داشتم از واردات مرموز زیرمسیر صرف نظر کنم و به نام مستعار مسیر TypeScript برگردم. اما پس از مطالعه مستندات بیشتر و مشکلات GitHub، راه حلی پیدا کردم!
تلاش شماره 5: شرایط سفارشی برای نجات
طبق اسناد Node.js، میتوانید از طریق شیء، نام مستعار وارداتی را به چندین مکان نگاشت کنید:
"imports": {
"#*": {
"condition-a": "./location-a/*",
"condition-b": "./location-b/*"
}
}
کلیدهای آن شیء را شرایط می گویند. شرایط داخلی مانند وجود دارد default
، require
یا import
، اما همچنین می تواند هر رشته سفارشی که توسط کاربر تعریف شده باشد وجود داشته باشد.
من اصلاح کردم imports
میدان در package.json
برای گنجاندن یک شرط سفارشی my-package-dev
با اشاره به src
و نگهداری کرد default
شرط اشاره به dist
:
"imports": {
- "#*": "./dist/src/*"
+ "#*": {
+ "my-package-dev": "./src/*",
+ "default": "./dist/*"
+ }
}
بنابراین، دو راه برای حل وجود دارد #
واردات:
-
my-package-dev
– به Node.js می گوید که مسیرها را ازsrc
دایرکتوری زمانی که شرط فعال است (در طول توسعه) -
default
– گزینه بازگشتی برای حل مسیرها ازdist
دایرکتوری زمانی که شرایط خاصی ارائه نشده باشد
توجه: من عمداً وضعیتم را نام بردم
my-package-dev
، نه فقطdev
. این برای نویسندگان کتابخانه مهم است. اگر مصرف کنندگان شما پروژه خود را باdev
شرایط، بسته شما درnode_modules
آن شرط را نیز در نظر می گیرد و سعی می کند فایل ها را ازsrc
! اگر برنامه کاربران نهایی را توسعه می دهید، می توانید استفاده کنیدdev
یاdevelopment
به عنوان نام شرط
پیکربندی TypeScript را به روز کنید
اکنون باید به TypeScript در مورد شرایط سفارشی خود اطلاع دهم. خوشبختانه، tsconfig.json
یک گزینه customConditions برای آن فراهم می کند. تمام تغییرات انجام شده در مراحل قبلی را برگردانده و اضافه کرده ام customConditions
زمینه:
// tsconfig.json
"compilerOptions": {
"target": "es2021",
"module": "NodeNext",
+ "customConditions": ["my-package-dev"],
"noEmit": true,
"skipLibCheck": true,
}
با این تنظیمات، TypeScript به درستی وارد کردن مسیرهای فرعی را از مسیر حل می کند src
دایرکتوری حتی بدون rootDir
و outDir
گزینه ها VSCode نیز به درستی پیمایش می کند utils.ts
مکان
پیکربندی Vitest را به روز کنید
Vitest همچنین از ارائه شرایط سفارشی پشتیبانی می کند. من تنظیم کرده ام resolve.conditions
در vitest.config.mts
:
import { defineConfig } from 'vitest/config';
export default defineConfig({
+ resolve: {
+ conditions: ['my-package-dev'],
+ },
});
پس از این تغییر، vitest در حال حل و فصل فایلها بود src
دایرکتوری که از بررسی کد واقعی در طول آزمایش اطمینان حاصل می کند:
ابزارهای دیگر
برای سایر ابزارها، باید اسناد آنها را در مورد پشتیبانی از شرایط سفارشی بررسی کنید. من سعی کردم پروژه ام را با tsx اجرا کنم. از آنجایی که از تمام پرچمهای Node.js پشتیبانی میکند، من به تازگی شرایط سفارشی را از طریق آن ارائه کردهام -C
پرچم:
$ npx tsx -C my-package-dev src/index.ts
42
کار می کند.
من می توانم یک مرور کلی از پشتیبانی واردات subpath در ابزارها و IDE های مختلف را توصیه کنم.
خلاصه
این یک سفر چالش برانگیز برای راه اندازی واردات فرعی بود. به خصوص هنگام اطمینان از سازگاری در جریان توسعه، ابزارهای آزمایش، پشتیبانی IDE و اجرای تولید.
با این حال، نتیجه موفقیت آمیز است و راه اندازی نهایی چیز خیلی پیچیده ای نیست. من مطمئن هستم که وارد کردن مسیرهای فرعی در نهایت به یک روش پیشفرض برای نام مستعار در پروژههای Node.js تبدیل خواهد شد. امیدوارم این مقاله در وقت شما صرفه جویی کند!
من یک نمونه کار نهایی را در GitHub منتشر کرده ام، شما می توانید آن را بررسی کنید. با تشکر برای خواندن و کد نویسی خوشحال! ❤️