Resolve
تتحكم هذه الخيارات في طريقة حل modules. يوفّر webpack إعدادات افتراضية مناسبة، ويمكنك تعديل سلوك resolver بالتفصيل عند الحاجة. راجع Module Resolution لفهم آلية عمل resolver بشكل أوضح.
resolve
object
خصّص طريقة حل modules. على سبيل المثال، عند استخدام import 'lodash' في ES2015، تحدد خيارات resolve الأماكن التي يبحث فيها webpack عن 'lodash' (راجع modules).
webpack.config.js
export default {
// ...
resolve: {
// خيارات التخصيص
},
};resolve.alias
object
أنشئ أسماء مستعارة لتسهيل استيراد modules معيّنة عبر import أو require. على سبيل المثال، يمكنك إنشاء alias لمجموعة من مجلدات src/ كثيرة الاستخدام:
webpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
// ...
resolve: {
alias: {
Utilities: path.resolve(__dirname, "src/utilities/"),
Templates: path.resolve(__dirname, "src/templates/"),
},
},
};الآن، بدلاً من استخدام المسارات النسبية عند الاستيراد بهذه الطريقة:
import Utility from "../../utilities/utility";يمكنك استخدام الاسم المستعار:
import Utility from "Utilities/utility";يمكنك أيضًا إضافة علامة $ في نهاية مفتاح alias للدلالة على التطابق التام فقط:
webpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
// ...
resolve: {
alias: {
xyz$: path.resolve(__dirname, "path/to/file.js"),
},
},
};ينتج عن ذلك السلوك التالي:
import Test1 from "xyz"; // تطابق تام، لذلك يتم حل path/to/file.js واستيراده
import Test2 from "xyz/file.js"; // ليس تطابقًا تامًا، لذلك تتم عملية resolve العاديةيمكنك أيضًا استخدام أحرف البدل (*) في تخصيص الاسم المستعار الخاص بك لإنشاء تعيينات أكثر مرونة:
webpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
// ...
resolve: {
alias: {
"@*": path.resolve(__dirname, "src/*"), // يربط @something بالمسار path/to/something
},
},
};يتيح لك هذا استخدام عمليات import مثل:
import Component from "@components/Button";
import utils from "@utils/helpers";ويوضح الجدول التالي الحالات الأخرى:
alias: | import 'xyz' | import 'xyz/file.js' |
|---|---|---|
{} | /abc/node_modules/xyz/index.js | /abc/node_modules/xyz/file.js |
{ xyz: '/abc/path/to/file.js' } | /abc/path/to/file.js | خطأ |
{ xyz$: '/abc/path/to/file.js' } | /abc/path/to/file.js | /abc/node_modules/xyz/file.js |
{ xyz: './dir/file.js' } | /abc/dir/file.js | خطأ |
{ xyz$: './dir/file.js' } | /abc/dir/file.js | /abc/node_modules/xyz/file.js |
{ xyz: '/some/dir' } | /some/dir/index.js | /some/dir/file.js |
{ xyz$: '/some/dir' } | /some/dir/index.js | /abc/node_modules/xyz/file.js |
{ xyz: './dir' } | /abc/dir/index.js | /abc/dir/file.js |
{ xyz: 'modu' } | /abc/node_modules/modu/index.js | /abc/node_modules/modu/file.js |
{ xyz$: 'modu' } | /abc/node_modules/modu/index.js | /abc/node_modules/xyz/file.js |
{ xyz: 'modu/some/file.js' } | /abc/node_modules/modu/some/file.js | خطأ |
{ xyz: 'modu/dir' } | /abc/node_modules/modu/dir/index.js | /abc/node_modules/modu/dir/file.js |
{ xyz$: 'modu/dir' } | /abc/node_modules/modu/dir/index.js | /abc/node_modules/xyz/file.js |
يمكن أن يتم resolve لـ index.js إلى ملف آخر إذا كان ذلك معرّفًا في package.json.
قد يتابع webpack البحث من /abc/node_modules إلى /node_modules أيضًا.
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
// ...
resolve: {
alias: {
_: [
path.resolve(__dirname, "src/utilities/"),
path.resolve(__dirname, "src/templates/"),
],
},
},
};ضبط resolve.alias على false يجعل webpack يتجاهل module.
export default {
// ...
resolve: {
alias: {
"ignored-module": false,
"./ignored-module": false,
},
},
};resolve.aliasFields
[string]: ['browser']
حدد حقلاً، مثل browser، ليتم تحليله وفقًا لـ هذه المواصفات.
webpack.config.js
export default {
// ...
resolve: {
aliasFields: ["browser"],
},
};resolve.byDependency
خصّص خيارات resolve حسب نوع طلب module.
-
النوع:
[type: string]: ResolveOptions -
مثال:
export default { // ... resolve: { byDependency: { // ... esm: { mainFields: ["browser", "module"], }, commonjs: { aliasFields: ["browser"], }, url: { preferRelative: true, }, }, }, };
resolve.cache
boolean
يفعّل caching للطلبات التي تم حلها بنجاح، مما يسمح بإعادة استخدام إدخالات cache والتحقق منها.
webpack.config.js
export default {
// ...
resolve: {
cache: true,
},
};resolve.cachePredicate
function(module) => boolean
دالة تقرر هل يجب تخزين الطلب في cache أم لا. يُمرر إليها object يحتوي على الخاصيتين path وrequest، ويجب أن ترجع boolean.
webpack.config.js
export default {
// ...
resolve: {
cachePredicate: (module) =>
// منطق إضافي
true,
},
};resolve.cacheWithContext
boolean
إذا كان unsafe cache مفعّلًا، فسيتم تضمين request.context داخل مفتاح cache. يأخذ module enhanced-resolve هذا الخيار في الحسبان. يتم تجاهل context في resolve caching عند توفير plugins لـ resolve أو resolveLoader. يساعد هذا على تجنب تراجع performance.
resolve.conditionNames
string[]
أسماء الشروط في حقل exports، وهي التي تحدد entry points الخاصة بالـ package.
webpack.config.js
export default {
// ...
resolve: {
conditionNames: ["require", "node"],
},
};يطابق webpack شروط التصدير المدرجة داخل array الخاصة بـ resolve.conditionNames.
القيم الافتراضية
يضبط webpack القيمة الافتراضية لـ conditionNames ديناميكيًا حسب إعدادات mode وtarget:
تتضمن الشروط الأساسية دائمًا ما يلي:
"webpack": موجود دائمًا."production"أو"development": حسب قيمةmodeالحالية. تُستخدم"production"عندما يكون الوضع"none"أو"production".
يتم إلحاق شروط إضافية بناءً على target:
قيمة target | الشرط |
|---|---|
webworker | "worker" |
node | "node" |
web | "browser" |
electron | "electron" |
nwjs | "nwjs" |
على سبيل المثال، مع target: "web" (الافتراضي) وmode: "production"، يكون الإعداد الافتراضي conditionNames هو ["webpack", "production", "browser"].
شروط كل نوع dependency
يضبط webpack قيمة conditionNames عبر resolve.byDependency حسب طريقة استيراد module. الرمز "..." يرث الشروط الأساسية المذكورة أعلاه.
| نوع dependency | conditionNames | الاستخدام |
|---|---|---|
esm، wasm، loaderImport | ["import", "module-sync", "module", "..."] | عمليات ESM import، وWebAssembly، وعمليات import من loaders |
commonjs، amd، loader، unknown، undefined | ["require", "module-sync", "module", "..."] | استدعاءات require() وAMD وأنواع dependency الأخرى |
worker | ["worker", "import", "module-sync", "module", "..."] | تعابير new Worker() |
css-import | ["webpack", <mode>, "style"] | تعليمات CSS @import |
يُدرج 5.107.0+ الشرط "module-sync" ضمن الشروط الافتراضية
للتوافق مع Node.js. هذا الشرط يعبّر عن حزم ESM التي يمكن تحميلها بشكل متزامن.
الحزم التي تنشر تصديرًا باسم module-sync داخل package.json تُلتقط تلقائيًا
بدون أي إعداد إضافي.
على سبيل المثال، عندما يستخدم ملف import في مشروع يحتوي على target: "web" وmode: "production"، فإن الشروط النهائية التي تم حلها هي ["import", "module-sync", "module", "webpack", "production", "browser"].
مطابقة الشروط
يعد ترتيب المفاتيح في الحقل exports مهمًا. أثناء مطابقة الشرط، تتمتع الإدخالات السابقة بأولوية أعلى وتكون لها الأسبقية على الإدخالات اللاحقة.
على سبيل المثال،
package.json
{
"name": "foo",
"exports": {
".": {
"import": "./index-import.js",
"require": "./index-require.js",
"node": "./index-node.js"
},
"./bar": {
"node": "./bar-node.js",
"require": "./bar-require.js"
},
"./baz": {
"import": "./baz-import.js",
"node": "./baz-node.js"
}
}
}webpack.config.js
export default {
// ...
resolve: {
conditionNames: ["require", "node"],
},
};عمليات import:
- سيتم resolve لـ
'foo'إلى'foo/index-require.js'. - سيتم resolve لـ
'foo/bar'إلى'foo/bar-node.js'لأن المفتاح"node"يأتي قبل"require"داخل object الخاص بالـ conditional exports. - سيتم resolve لـ
'foo/baz'إلى'foo/baz-node.js'.
شروط مخصصة
إذا كنت تريد إضافة أسماء الحقول المخصصة الخاصة بك مع الاحتفاظ بالقيم الافتراضية webpack، فيمكنك استخدام "...":
webpack.config.js
export default {
// ...
resolve: {
conditionNames: ["my-custom-condition", "..."],
},
};أو إذا أردت إعطاء الأولوية للشروط الافتراضية أولًا، ثم إضافة شروطك المخصصة:
webpack.config.js
export default {
// ...
resolve: {
conditionNames: ["...", "my-custom-condition"],
},
};resolve.descriptionFiles
[string] = ['package.json']
ملفات JSON المستخدمة للأوصاف.
webpack.config.js
export default {
// ...
resolve: {
descriptionFiles: ["package.json"],
},
};resolve.enforceExtension
boolean = false
إذا كانت القيمة true، فلن يسمح webpack بالاستيراد بدون الامتداد الكامل. لذلك يعمل import foo from "./foo"; أو require('./foo') افتراضيًا إذا كان ./foo يملك امتداد .js، لكن عند تفعيل هذا الخيار لن يعمل إلا import foo from "./foo.js" أو require('./foo.js').
webpack.config.js
export default {
// ...
resolve: {
enforceExtension: false,
},
};resolve.exportsFields
[string] = ['exports']
الحقول الموجودة في package.json التي تُستخدم لحل طلبات module. راجع دليل package exports لمزيد من المعلومات.
webpack.config.js
export default {
// ...
resolve: {
exportsFields: ["exports", "myCompanyExports"],
},
};resolve.extensionAlias
object
object يربط امتدادًا بامتدادات بديلة.
webpack.config.js
export default {
// ...
resolve: {
extensionAlias: {
".js": [".ts", ".js"],
".mjs": [".mts", ".mjs"],
},
},
};resolve.extensions
[string] = ['.js', '.json', '.wasm']
يحاول webpack resolve هذه الامتدادات بالترتيب. إذا كانت هناك ملفات متعددة لها الاسم نفسه لكن بامتدادات مختلفة، فسيختار webpack الملف صاحب الامتداد المذكور أولًا في array ويتخطى الباقي.
webpack.config.js
export default {
// ...
resolve: {
extensions: [".js", ".json", ".wasm"],
},
};وهو ما يمكّن المستخدمين من ترك الامتداد عند الاستيراد:
import File from "../path/to/file";لاحظ أن استخدام resolve.extensions كما في المثال أعلاه يلغي array الافتراضية، مما يعني أن webpack لن يحاول resolve modules باستخدام الامتدادات الافتراضية. يمكنك استخدام '...' لإبقاء الامتدادات الافتراضية:
export default {
// ...
resolve: {
extensions: [".ts", "..."],
},
};resolve.fallback
object
يوجّه طلبات module إلى بدائل عند فشل resolve العادي.
webpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
// ...
resolve: {
fallback: {
abc: false, // لا تضف polyfill لـ abc
xyz: path.resolve(__dirname, "path/to/file.js"), // أضف polyfill لـ xyz
},
},
};في webpack 5 لم يعد webpack يضيف polyfills تلقائيًا لـ Node.js core modules. إذا كنت تستخدم هذه modules في كود يعمل داخل browser أو بيئة مشابهة، فعليك تثبيت الحزم المتوافقة من npm وإضافتها بنفسك. هذه قائمة بالـ polyfills التي كان webpack يستخدمها قبل webpack 5:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
export default {
// ...
resolve: {
fallback: {
assert: require.resolve("assert"),
buffer: require.resolve("buffer"),
console: require.resolve("console-browserify"),
constants: require.resolve("constants-browserify"),
crypto: require.resolve("crypto-browserify"),
domain: require.resolve("domain-browser"),
events: require.resolve("events"),
http: require.resolve("stream-http"),
https: require.resolve("https-browserify"),
os: require.resolve("os-browserify/browser"),
path: require.resolve("path-browserify"),
punycode: require.resolve("punycode"),
process: require.resolve("process/browser"),
querystring: require.resolve("querystring-es3"),
stream: require.resolve("stream-browserify"),
string_decoder: require.resolve("string_decoder"),
sys: require.resolve("util"),
timers: require.resolve("timers-browserify"),
tty: require.resolve("tty-browserify"),
url: require.resolve("url"),
util: require.resolve("util"),
vm: require.resolve("vm-browserify"),
zlib: require.resolve("browserify-zlib"),
},
},
};resolve.fullySpecified
boolean
عند ضبطه على true، يتعامل هذا الخيار مع الطلبات التي يكتبها المستخدم على أنها محددة بالكامل. هذا يعني أنه لا تُضاف امتدادات تلقائيًا، ولا يتم resolve للملفات الرئيسية داخل المجلدات. لاحظ أن هذا السلوك لا يؤثر على الطلبات القادمة من mainFields أو aliasFields أو aliases.
webpack.config.js
export default {
// ...
resolve: {
fullySpecified: true,
},
};resolve.importsFields
[string]
الحقول في package.json التي تُستخدم لتوفير الطلبات الداخلية للـ package. الطلبات التي تبدأ بـ # تُعد داخلية.
webpack.config.js
export default {
// ...
resolve: {
importsFields: ["browser", "module", "main"],
},
};resolve.mainFields
[string]
عند الاستيراد من npm package، مثل import * as D3 from 'd3'، يحدد هذا الخيار أي حقول من package.json يستخدمها webpack كنقطة دخول. تختلف القيم الافتراضية حسب target المحدد في إعداد webpack.
عند ضبط الخاصية target على webworker أو web أو تركها غير محددة:
webpack.config.js
export default {
// ...
resolve: {
mainFields: ["browser", "module", "main"],
},
};لأي target آخر، بما في ذلك node:
webpack.config.js
export default {
// ...
resolve: {
mainFields: ["module", "main"],
},
};على سبيل المثال، افترض وجود library اسمها upstream وملف package.json الخاص بها يحتوي على الحقول التالية:
{
"browser": "build/upstream.js",
"module": "index"
}عند كتابة import * as Upstream from 'upstream'، سيتم resolve للاستيراد إلى الملف الموجود في الخاصية browser. تحصل الخاصية browser على الأولوية لأنها أول عنصر في mainFields. وفي المقابل، سيحاول تطبيق Node.js المجمّع بواسطة webpack أن يستخدم الملف الموجود في الحقل module أولًا.
resolve.mainFiles
[string] = ['index']
اسم الملف الذي سيتم استخدامه أثناء حل الدلائل.
webpack.config.js
export default {
// ...
resolve: {
mainFiles: ["index"],
},
};resolve.modules
[string] = ['node_modules']
أخبر webpack بأي مجلدات يبحث فيها عند resolve للـ modules.
يمكن استخدام كل من المسارات المطلقة والنسبية، لكن انتبه إلى أن سلوكهما سيكون مختلفًا بعض الشيء.
سيتم فحص المسار النسبي بشكل مشابه لكيفية فحص Node بحثًا عن node_modules، من خلال البحث في الدليل الحالي بالإضافة إلى أسلافه (أي ./node_modules، ../node_modules، وما إلى ذلك).
مع المسار المطلق، سيتم البحث فقط في الدليل المحدد.
webpack.config.js
export default {
// ...
resolve: {
modules: ["node_modules"],
},
};إذا أردت إضافة مجلد بحث تكون له أولوية أعلى من node_modules/:
webpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
// ...
resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"],
},
};resolve.plugins
قائمة resolve plugins إضافية يجب تطبيقها.
يمكن أن يكون كل عنصر واحدًا مما يلي:
- plugin object يملك الدالة
apply(resolver). - function plugin تُستدعى ويكون resolver هو قيمة
thisوالـ argument الأول.
يتيح ذلك استخدام plugins مثل DirectoryNamedWebpackPlugin.
webpack.config.js
export default {
// ...
resolve: {
plugins: [
// plugin بأسلوب object
{
apply(resolver) {
// منطق مخصص
},
},
// plugin بأسلوب function
function (resolver) {
// `this` هو resolver أيضًا
},
],
},
};resolve.preferAbsolute
boolean
يفضّل المسارات المطلقة على resolve.roots أثناء resolve.
webpack.config.js
export default {
// ...
resolve: {
preferAbsolute: true,
},
};resolve.preferRelative
boolean
عند تفعيله، يفضّل webpack حل طلبات module كطلبات نسبية بدل استخدام modules من مجلدات node_modules.
webpack.config.js
export default {
// ...
resolve: {
preferRelative: true,
},
};src/index.js
// لنفترض أن `src/logo.svg` موجود
import logo1 from "logo.svg"; // يعمل هذا عندما يكون `preferRelative` مفعّلًا
import logo2 from "./logo.svg"; // وإلا فيجب استخدام مسار نسبي لحل logo.svg
// `preferRelative` مفعّل افتراضيًا في حالة `new URL()`
const b = new URL("module/path", import.meta.url);
const a = new URL("./module/path", import.meta.url);resolve.restrictions
[string, RegExp]
قائمة قيود تحدد المسارات المسموح للطلبات أن تُحل إليها.
webpack.config.js
export default {
// ...
resolve: {
restrictions: [/\.(sass|scss|css)$/],
},
};resolve.roots
[string]
قائمة المجلدات التي تُحل منها طلبات URL المرتبطة بجذر server، وهي الطلبات التي تبدأ بـ /. القيمة الافتراضية هي خيار context. في الأنظمة غير Windows، تُحل هذه الطلبات كمسار مطلق أولًا.
webpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const fixtures = path.resolve(__dirname, "fixtures");
export default {
// ...
resolve: {
roots: [__dirname, fixtures],
},
};resolve.symlinks
boolean = true
يحدد هل يتبع resolver الروابط الرمزية إلى المسار الحقيقي للملف.
عند تفعيله، تُحوّل الموارد المشار إليها عبر symlink إلى مسارها _الحقيقي، وليس إلى موقع symlink نفسه. لاحظ أن هذا قد يسبب فشل resolve للـ module عند استخدام أدوات تربط packages، مثل npm link.
webpack.config.js
export default {
// ...
resolve: {
symlinks: true,
},
};resolve.unsafeCache
object boolean = true
يفعّل caching قويًا لكنه غير آمن للـ modules. تمرير true سيخزّن كل شيء في cache.
webpack.config.js
export default {
// ...
resolve: {
unsafeCache: true,
},
};عند تمرير object، سيستخدمه webpack كـ cache.
على سبيل المثال، يمكنك تمرير كائن Proxy بدل object عادي:
webpack.config.js
// منقول من المناقشة هنا https://github.com/webpack/webpack/discussions/18089
const realUnsafeCache = {};
const unsafeCacheHandler = {
get(cache, key) {
const cachedValue = cache[key];
// تأكد من وجود الملف على القرص
if (cachedValue && !fs.existsSync(cachedValue.path)) {
// وإذا لم يكن موجودًا، احذف إدخال cache.
delete cache[key];
return undefined;
}
return cachedValue;
},
};
const theProxiedCache = new Proxy(realUnsafeCache, unsafeCacheHandler);
export default {
// ...
resolve: {
unsafeCache: theProxiedCache,
},
};resolve.useSyncFileSystemCalls
boolean
يستخدم استدعاءات نظام الملفات المتزامنة داخل resolver.
webpack.config.js
export default {
// ...
resolve: {
useSyncFileSystemCalls: true,
},
};resolve.tsconfig
5.105.0+boolean string object
إعداد TypeScript لتعيين المسارات. يغني هذا الخيار عن الحاجة إلى tsconfig-paths-webpack-plugin. يقرأ compilerOptions.baseUrl وcompilerOptions.paths من tsconfig.json ويطبق تلك الأسماء المستعارة أثناء resolve لعمليات import.
webpack.config.js
export default {
// ...
resolve: {
tsconfig: true, // استخدم tsconfig.json الافتراضي
},
};الخيارات:
false- تعطيل path mapping الخاص بـ TypeScripttrue- استخدم ملفtsconfig.jsonالافتراضي (يبحث عنه تلقائيًا)string- المسار إلى ملفtsconfig.json(نسبي أو مطلق)
webpack.config.js
export default {
// ...
resolve: {
tsconfig: "./tsconfig.app.json", // مسار مخصص
},
};object- object يحتوي على خياريconfigFileوreferences
webpack.config.js
export default {
// ...
resolve: {
tsconfig: {
configFile: "./tsconfig.json",
references: "auto", // أو array من المسارات
},
},
};خيارات object:
configFile(string): مسار إلى ملف tsconfig (نسبي أو مطلق)references("auto"|string[]): مراجع لملفات tsconfig الأخرى."auto"يرث من إعداد TypeScript، أو يمكنك تمرير array من المسارات النسبية/المطلقة.
مثال tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"components/*": ["src/components/*"]
}
}
}ثم في الكود الخاص بك:
import Button from "@/components/Button";
import Header from "components/Header";ResolveLoader
object { modules [string] = ['node_modules'], extensions [string] = ['.js', '.json'], mainFields [string] = ['loader', 'main']}
هذه المجموعة من الخيارات تطابق خاصية resolve المذكورة أعلاه، لكنها تُستخدم فقط لـ resolve حزم loaders الخاصة بـ webpack.
webpack.config.js
export default {
// ...
resolveLoader: {
modules: ["node_modules"],
extensions: [".js", ".json"],
mainFields: ["loader", "main"],
},
};


