Module.exports با import به سبک es6 برای webpack.config.ts در تایپاسکریپت
من از وبپک همراه با تایپاسکریپت استفاده میکنم و تنظیمات آن خود در تایپاسکریپت است. دستورالعملها اینجا
در ریشه خود فایل webpack.config.base.ts را دارم
import webpack from "webpack";
const getConfig = ( appDir: string, distDir: string, env: any, args: any ): webpack.Configuration => {
const config: webpack.Configuration = {
entry: {
},
output: {
},
resolve: {
plugins: [
],
extensions: [".ts", ".tsx", ".js"]
},
devtool: "source-map",
module: {
rules: [
]
},
plugins: [
]
};
return config;
};
module.exports = getConfig;
سپس من دو پروژه دارم که هر کدام فایل webpack.config.ts خود را دارند
import webpack from "webpack";
import * as path from 'path';
const getConfig = require("../../webpack.config.base");
const appDir = __dirname;
const distDir = path.resolve(__dirname, "../AppOne.Web/wwwroot");
const getConfigFactory = (env: any, args: any): webpack.Configuration => getConfig(appDir, distDir, env, args);
module.exports = getConfigFactory;
این همه کاملاً به خوبی کار میکند. در اینجا یک مثال کامل از این سبک کارخانه getConfig =() => {} آمده است.
مشکل من این است که وقتی تلاش میکنم تغییر کنم
const getConfig = require("../../webpack.config.base");
به یک واردات es6. این حتی به عنوان یک پیشنهاد توسط VS code ارائه شده است.
وقتی این تغییر را اعمال میکنم، دریافت میکنم
این هم tsconfig.json من است. من قبلاً [allowSyntheticDefaultImports][5] را فعال کردهام. اینجا پیشنهاد شده است.
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"moduleResolution": "node",
"jsx": "react",
"experimentalDecorators": true,
"lib": [
"es2015",
"dom"
],
"target": "es5",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"typeRoots": [
"./node_modules/@types/",
"./types/"
],
"baseUrl": ".",
"paths": { }
},
"include": [
"./src/**/*.ts",
"./src/**/*.tsx"
]
}
اما من با این حال export default getConfig; را اضافه کردم... و دوباره npm run build را اجرا کردم. هنوز هم شکست میخورد.
const getConfigFactory = (env: any, args: any): webpack.Configuration => getConfig(appDir, distDir, env, args);
^
TypeError: webpack_config_base_1.default is not a function
آخرین تلاش من قبل از کوبیدن سرم به میز، تغییر بود
import getConfig from "../../webpack.config.base";
import * as base from "../../webpack.config.base";
کد export default getConfig; را در webpack.config.base.ts حذف کنید و const getConfig را مستقیماً به صورت export const getConfig صادر کنید. اما در این مرحله، معنای module.exports=getConfig چیست؟ به علاوه، این هم اصلاً کار نمیکند (همان مشکل قبلی).
const getConfigFactory = (env: any, args: any): webpack.Configuration => base.getConfig(appDir, distDir, env, args);
^
TypeError: base.getConfig is not a function
اینجا چه چیزی را از دست میدهم؟ چرا نمیتوانم به سادگی const getConfig=require("../../webpack.config.base"); را با import getConfig from "../../webpack.config.base" جایگزین کنم؟
ضمناً
اینجا «scripts» من برای اجرای این است
"build:appone": "webpack --mode=development --config ./src/AppOne.App/webpack.config.ts",
"build:apptwo": "webpack --mode=development --config ./src/AppTwo.App/webpack.config.ts",
پاسخ شماره ۱
چه چیزی کار میکند؟
من webpack را با TypeScript برای محیطهای مختلف (مثلاً development و production) با یک پیکربندی پایه مشترک پیکربندی کردم. برای این کار، از موارد زیر استفاده میکنم:
- Node.js (نسخه
11.12.0) - تایپاسکریپت (نسخه
3.5.3) - webpack (نسخه
4.39.1)
ساختار دایرکتوری
فرض کنید ساختار دایرکتوری زیر وجود دارد :
project/
├── ...
├── webpack.common.ts
├── webpack.development.ts
└── webpack.production.ts
ساختارهای دایرکتوری دیگر (مانند دو پروژه تو در تو همانطور که در مثال شما است) نیز کار خواهند کرد. اگرچه، ممکن است نیاز باشد مسیرهای استفاده شده در مثالهای زیر را تطبیق دهید.
پیکربندی تایپاسکریپت
پیکربندی پایه webpack، webpack.common.ts، به صورت زیر است:
import webpack from 'webpack';
const configuration: webpack.Configuration = {
// Your common webpack configuration...
};
export default configuration;
دو پیکربندی webpack برای محیطهای مختلف این پیکربندی پایه را با استفاده از بسته npm webpack-merge گسترش میدهند. میتوانید تایپهای آن را برای TypeScript در بسته npm @types/webpack-merge پیدا کنید. برای پایبندی به مثال اولیه، پیکربندی webpack برای محیط development به صورت زیر است:
import webpack from 'webpack';
import merge from 'webpack-merge';
import commonWebpackConfiguration from './webpack.common';
const configuration: webpack.Configuration = merge(commonWebpackConfiguration, {
mode: 'development'
// Your `development`-specific configuration...
});
export default configuration;
در همین حال، پیکربندی webpack برای محیط production از نظر نحو import/export تفاوتی با محیط development ندارد.
واردات و صادرات
همانطور که ممکن است متوجه شده باشید، من از نحو ES6 import/export استفاده میکنم:
export default configuration;
و
import commonWebpackConfiguration from './webpack.common';
بنابراین، هیچ نحو CommonJS برای واردات و صادرات (مثلاً module.exports یا require) وجود ندارد که فایلهای پیکربندی webpack را تمیز نگه میدارد و اجازه میدهد تا یک جریان کاری بدون مشکل داشته باشید. در واقع، این روش توصیه شده برای کار با webpack و TypeScript مطابق با مستندات webpack است.
چرا پیکربندی شما کار نمیکند؟
اولین تلاش
مشکل من این است که وقتی تلاش میکنم تغییر دهم
const getConfig = require("../../webpack.config.base");به یک واردات ES6. این حتی به عنوان یک پیشنهاد توسط VS Code ارائه شده است.
module.exports در واقع هیچ صادرات پیشفرضی ندارد (یعنی شیء module.exports هیچ ویژگی با نام default ندارد) همانطور که خطایی که مشاهده کردید نشان میدهد.
استفاده از صادرات پیشفرض ES6 (یعنی export default) در واقع یک صادرات به نام default ایجاد میکند درست مانند سایر صادرات به نام (مثلاً bar در مثال زیر). این را میتوان با کامپایل قطعهکد TypeScript زیر نشان داد:
const helloWorld = () => {
console.log('Hello, world!');
};
const bar = 'foo';
export default helloWorld;
export { bar };
به جاوااسکریپت با استفاده از tsc:
"use strict";
exports.__esModule = true;
var helloWorld = function () {
console.log('Hello, world!');
};
var bar = 'foo';
exports.bar = bar;
exports["default"] = helloWorld;
دومین تلاش
اما من با این حال
export default getConfig;را اضافه کردم... و دوبارهnpm run buildرا اجرا کردم. هنوز هم شکست میخورد.
در این مورد، اضافه کردن allowSyntheticDefaultImports (که شما قبلاً آن را دارید) و esModuleInterop (که شما از آن غافل هستید) به پیکربندی TypeScript خود tsconfig.json و تنظیم هر دو روی true مشکل را برطرف میکند 1.
سومین تلاش
آخرین تلاش من قبل از کوبیدن سرم به میز، تغییر بود
import getConfig from "../../webpack.config.base";به
import * as base from "../../webpack.config.base";کد
export default getConfig;را درwebpack.config.base.tsحذف کنید وconst getConfigرا مستقیماً به صورتexport const getConfigصادر کنید. اما در این مرحله،module.exports=getConfigچه فایدهای دارد.
داشتن
export const getConfig = () => {...};
و
module.exports = getConfig;
در همان زمان، به شما base === getConfig میدهد (زیرا تنها module.exports=getConfig; تأثیر دارد). در نتیجه، فراخوانی base.getConfig مقدار undefined میدهد زیرا تابع تعریفشده شما getConfig ویژگی getConfig را ندارد. بنابراین، "base.getConfig یک تابع نیست".
تعاملی بودن نحو واردات
چرا نمیتوانم به سادگی
const getConfig=require("../../webpack.config.base");را باimport getConfig from "../../webpack.config.base"جایگزین کنم؟
const getConfig = require("../../webpack.config.base");
یک واردات CommonJS در حالی که
import getConfig from "../../webpack.config.base";
یک ES6 واردات است. آنها نمیتوانند به طور متقابل استفاده شوند زیرا ذاتاً متفاوت هستند. شما باید انتخاب کنید با یکی از آنها کار کنید، اما نه هر دوی آنها به طور همزمان.

