Как упаковать большой фреймворк в Typescript с помощью Webpack

Я пытаюсь создать фреймворк на TypeScript и связать все это с Webpack.

Проблема, с которой я столкнулся, заключается в том, что я не уверен, какой должна быть «точка входа», и когда точка входа установлена ​​для всех файлов, браузеру доступен только последний созданный файл.

И когда установлена ​​единственная точка входа, Ни один из зависимых классов не отображается (иначе говоря, отображается только класс точки входа).

Деталь:

Мой фреймворк TypeScript довольно большой, на данный момент в нем чуть более 140 модулей, но после его завершения он вырастет до тысячи.

Каждый модуль в «bean-компоненте» содержит один экспортированный класс и несколько операторов импорта (импортированные классы из других модулей в структуре).

моя структура папок в настоящее время состоит из:

+---src
|   +---API
|   +---bean
|   |   +---base
|   |   |   \---impl
|   |   +---categoryscheme
|   |   |   \---impl
|   |   +---codelist
|   |   |   \---impl
|   |   +---conceptscheme
|   |   |   \---impl
|   |   +---constraint
|   |   |   \---impl
|   |   +---datastructure
|   |   |   \---impl
|   |   +---hierarchicalcodelist
|   |   |   \---impl
|   |   +---metadatastructure
|   |   |   \---impl
|   |   +---organisation
|   |   |   \---Impl
|   |   +---reference
|   |   \---structuremap
|   |       \---impl
|   +---enums
|   +---typings
|   \---util

Где каждый impl содержит экспортированный класс, а родительские папки содержат интерфейсы.

Моя первая проблема заключается в том, что этот фреймворк не является приложением или однофайловой библиотекой, он предназначен для людей, которые могут делать такие вещи, как:

var f = new CodeListBeanImpl();

или какой бы класс они ни выбрали.

Не вдаваясь в подробности, причина этих файлов в том, что существует определенная Иерархия структур.

Например, класс CodelistBeanImpl в папке codelist / impl имеет следующую иерархию: см изображение

Каждый файл разбросан по разным адресам. в основной папке.

Итак, без четкой «точки входа» в структуру я не могу заставить webpack просто объединить все модули в один файл и сделать его доступным для вызова браузером.

вот моя конфигурация веб-пакета:

const CircularDependencyPlugin = require('circular-dependency-plugin');
const path = require("path");
const glob = require("glob");
let list = glob.sync("./src/**/*.ts");
module.exports = {
    entry: list,
    devtool: 'source-eval-map',
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: 'ts-loader',
                exclude: [
                    /node_modules/
                ]
            }
        ]
    },
    mode: "development",
    resolve: {
        extensions: [ '.tsx', '.ts', '.js' ],
        modules: ["./node_modules", "./src"]
    },
    plugins: [
        new CircularDependencyPlugin({
            failOnError: true,
            cwd: process.cwd(),
        }),
],
    output: {
        path: path.join(__dirname, "dist"),
        filename: "bundle.js",
        libraryTarget: "window",
        library: "IMJS",
    }
};

Теперь, как видите, я хочу, чтобы ВСЕ модули были упакованы, поэтому моя точка входа - КАЖДЫЙ файл, чтобы убедиться, что все модули и классы упакованы.

вот результат работы webpack:

[./src/API/IM.ts] 2.74 KiB {main} [built]
[./src/bean/base/impl/AnnotableBeanImpl.ts] 5.93 KiB {main} [built]
[./src/bean/base/impl/AnnotationBeanImpl.ts] 5.5 KiB {main} [built]
[./src/bean/base/impl/BeanImpl.ts] 3.52 KiB {main} [built]
[./src/bean/base/impl/ComponentBeanImpl.ts] 5.44 KiB {main} [built]
[./src/bean/base/impl/DataMetricsBeanImpl.ts] 3.22 KiB {main} [built]
[./src/bean/base/impl/IdentifiableBeanImpl.ts] 6.67 KiB {main} [built]
[./src/bean/base/impl/ItemBeanImpl.ts] 1.15 KiB {main} [built]
[./src/bean/base/impl/ItemSchemeBeanImpl.ts] 6.36 KiB {main} [built]
[./src/bean/base/impl/JsonBeanImpl.ts] 6.34 KiB {main} [built]
[./src/bean/base/impl/MaintainableBeanImpl.ts] 9.27 KiB {main} [built]
[./src/bean/base/impl/MetricsBeanImpl.ts] 2.03 KiB {main} [built]
[./src/bean/base/impl/NameableBeanImpl.ts] 6.97 KiB {main} [built]
[./src/bean/base/impl/PseudoHierarchyItemImpl.ts] 2.53 KiB {main} [built]
    + 181 hidden modules

Пока все хорошо ...

Однако когда я это сделаю. и запустите файл "bundle.js" в браузере, единственное, что IMJS (имя библиотеки, которое я решил использовать) - это ПОСЛЕДНИЙ созданный файл: образ хромированной консоли

Поэтому я пытаюсь сделать единственную «точку входа» в качестве теста, чтобы увидеть, могу ли я получить что-нибудь, кроме одного файла.

Меняю entry: list, на entry: "./src/bean/codelist/impl/CodelistBeanImpl.ts",

и построим его снова, на этот раз будет собран только небольшой набор файлов: Вывод Webpack для единой точки входа

Однако, когда я перехожу к консоли Chrome, единственный доступный мне класс - это CodelistBeanImpl, ни один из его суперклассов, поэтому я могу:

var f = new IMJS.CodelistBeanImpl();

но если я хочу, скажем, выполнить проверку instanceof для 'PseudoHierarchyItemSchemeImpl' он бы заявил, что «PseudoHierarchyItemSchemeImpl» не определен, фактически, не определено ничего, кроме bean-компонента списка кодов.

Возможно ли это даже с веб-пакетом? или мне нужно использовать другой упаковщик?

просто для справки, вот мой tsconfig.json:

{
  "compilerOptions": {
    "outDir": "./lib/",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "baseUrl": "./src",
    "module": "amd",
    "target": "es5",
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": false,
    "checkJs": false,
    "strictNullChecks": false,
    "strictFunctionTypes": true,
    "downlevelIteration": true,
    "lib":[
      "es2015",
      "dom"
    ]
  },
  "compileOnSave": true,
  "include": ["./src/**/*.ts"]
}
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
3
0
234
1

Ответы 1

Мне удалось добиться того, что я хотел создать файл вне папки src под названием «main.ts» и программно создать экспорт для каждого класса.

Не лучшее решение, поэтому оставайтесь открытыми, если у кого-то есть идея получше:

webpack.config.js:

 function createEntryPoint(){
        console.info("creating entry point...");
        const glob = require("glob");
        let typeScriptConfigFile = require("./tsconfig");
        let baseUrl = typeScriptConfigFile.compilerOptions.baseUrl;
        if (!baseUrl){
            throw new Error("Unable to find baseUrl in tsconfig");
        }
        let list = glob.sync(baseUrl+"/**/*.ts");
        const fs = require('fs');
        let num = 0;
        fs.writeFileSync('./main.ts', (function () {
            let strToReturn = "";
            for (let file of list) {
                num++;
                let fromBaseUrl = file.replace(baseUrl+"/", "");
                fromBaseUrl = fromBaseUrl.replace(".ts", "");
                strToReturn += "export * from '" + fromBaseUrl + "'; \n";
            }
            return strToReturn;
        }()));

        console.info("Entry point created: " +num + " modules exported");
    }
    createEntryPoint();

и точка входа:

entry: "./main.ts",

Другие вопросы по теме