در حین import ماژولهای TypeScript ایی پس از مدتی به یک چنین کدهایی خواهیم رسید:
import { SpecialCollection } from "../../special";
import { LoginComponent } from "../login";
import { TextUtils } from ".../../utils/text";
import { Router } from "../../../core/router";
در این حالت، در یک پوشه برای import ماژولی مشخص، چنین import ایی را خواهیم داشت:
import { Data } from '../data';
و در پوشهی تو در توی دیگری، این تعریف به صورت زیر تغییر میکند:
import { Data } from '../../../data';
و در آخر برنامه پر میشود از مسیرهای نسبی ‘../../../..’ مانند. به این ترتیب جابجا کردن فایلها و Refactoring آنها، مشکل میشود.
خوشبختانه کامپایلر TypeScript به همراه تنظیمات baseUrl و paths است که توسط آنها میتوان این مسیرهای نسبی را به مسیرهای مطلق تبدیل کرد و در این حالت اهمیتی ندارد که ماژول مدنظر از چه سطحی و درون چه پوشهی تو در تویی فراخوانی میشود، این مسیر import همواره ثابت خواهد بود.
تنظیمات فایل tsconfig.json برای معرفی مسیرهای مطلق ماژولها
فرض کنید میخواهید از یکی از سرویسهای
Core Module استفاده کنید:
بسته به عمق پوشهی استفاده کننده، به یک چنین تعریفی خواهید رسید:
import { BrowserStorageService } from "./../../core/browser-storage.service";
برای بهبود این وضعیت، فایل tsconfig.json و یا همان تنظیمات کامپایلر TypeScript را به نحو ذیل تکمیل میکنیم:
{
"compilerOptions": {
"baseUrl": "src",
"paths": {
"@app/*": [
"app/*"
],
"@app/core/*": [
"app/core/*"
],
"@app/shared/*": [
"app/shared/*"
],
"@env/*": [
"environments/*"
]
}
}
}
در اینجا baseUrl به پوشهی src برنامه اشاره میکند و مسیرهای بعدی بر این اساس محاسبه میشوند. در ادامه در قسمت paths، ابتدا یک نام مستعار ذکر میشود و سپس مسیری که ارائه دهندهی آن است. ذکر @ در اینجا اختیاری است؛ اما ذکر */ها اجباری است.
پس از این تغییرات، اکنون
افزونهی پیشنهاد دهندهی imports، هر دو حالت استفادهی از مسیر مطلق بر اساس نام مستعار تعریف شده:
import { BrowserStorageService } from "@app/core/browser-storage.service";
و یا استفادهی از مسیر نسبی را نیز پیشنهاد میدهد:
import { BrowserStorageService } from "./../../core/browser-storage.service";
برای مثال اگر دقت کرده باشید، روش import اجزای خود Angular به صورت زیر است:
import { Component } from '@angular/core';
علت اینجا است که Angular از تعریف مشابهی به صورت زیر برای نگاشت پوشهی node_modules آن به angular@ استفاده میکند:
"paths": {
"@angular/*": ["node_modules/@angular/*"]
},
و ذکر @ اختیاری هم از اینجا اقتباس شدهاست.
یک نکتهی مهم: تنظیمات فوق بدون تنظیمات معادل webpack ناقص هستند
اگر از برنامهی Angular CLI استفاده میکنید، تنظیمات ذکر شده، تا همینجا به پایان میرسند؛ چون webpack جزئی از Angular CLI است و تنظیمات پیش فرض آن، قسمت baseUrl و paths فایل tsconfig.json را به صورت خودکار پردازش میکند. اما اگر از TypeScript در محیطهای دیگری استفاده میکنید که از webpack به صورت مجزایی استفاده میکنند، نیاز است قسمت resolve.alias فایل webpack.config.js را نیز جهت معرفی این تغییرات، اصلاح کنید. از این جهت که کامپایلر TypeScript این مسیرهای مطلق را در حین تولید فایلهای نهایی JavaScript ایی معادل، به مسیرهای نسبی بازنویسی نمیکند و در این حالت webpack نمیداند که چطور باید این ماژولها را یافته و یکی کند.
resolve: {
extensions: ['*', '.js', '.ts'],
modules: [
rootDir,
path.join(rootDir, 'node_modules')
],
alias: {
'@app': 'src/app'
}
},
کوتاه کردن مسیرهای مطلق با معرفی فایل ویژهی index.ts
تا اینجا بجای ذکر مسیر
import { BrowserStorageService } from "./../../core/browser-storage.service";
به مسیر مطلق زیر رسیدیم (صرفنظر از محل قرارگیری ماژولی که قرار است آنرا import کند):
import { BrowserStorageService } from "@app/core/browser-storage.service";
این را هم میخواهیم به صورت زیر کوتاهتر کنیم:
import { BrowserStorageService } from "@app/core";
یعنی فقط app/core@ را ذکر کنیم.
برای اینکار نیاز است فایل ویژهای را به نام index.ts، در ریشهی پوشهی core ایجاد کنیم (src\app\core\index.ts)، با این محتوا:
export * from "./browser-storage.service";
export * from "./app-config.service";
export * from "./seo-service";
در اینجا تمام ماژولهایی که توسط Core Module ارائه میشوند را یکبار export میکنیم.
برای نمونه اگر به پوشهی node_modules\@angular خود مجموعهی Angular هم مراجعه کنید، هر پوشهی src آن به همراه یک فایل index.d.ts شبیه تعاریف فوق نیز هست.
پس از افزودن فایل index.ts به ریشهی پوشهی مدنظر، اکنون در لیست پیشنهادات، ذکر app/core@ تنها نیز ظاهر شده و استفادهی از آن مجاز است: