Как я могу создать пакет с зависимостями, связанными индивидуально - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть требование создать JavaScript-фреймворк для стороннего плагина, где плагин может использовать любые зависимости и любые версии тех зависимостей, которые он хочет, без конфликта с другими сторонними плагинами, которые используются на той же странице.

Мне также нужно подумать о том, чтобы разделить зависимости между плагинами, чтобы мы не заканчивали с x числом плагинов, использующих одну и ту же зависимость и версию, и раздували страницу с x номером той же зависимости.

Моя первоначальная идея состояла в том, чтобы использовать Webpack для объединения сторонних плагинов, но мне нужно было иметь отдельные пакеты для каждой отдельной зависимости, чтобы уменьшить раздувание страниц.Поэтому я добавил эту конфигурацию в конфигурацию для веб-пакета:

module.exports = {
    entry: {
        pluginX: './src/index.js',
    },
    devtool: 'source-map',
    target: 'web',
    output: {
        path: path.resolve(__dirname, './dist'),
        library: 'pluginX',
    },
    optimization: {
        moduleIds: 'named',
        chunkIds: 'named',        
        splitChunks: {
            chunks: 'all',
            name(module, chunk, cacheGroupKey) {
                const context = module.context;
                const splitContext = context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/);

                const packageJson = getPackageJson(context);
                const version = packageJson ? packageJson.version : '0.0.0';
                const name = splitContext[1].replace('@', '');
                return `${cacheGroupKey}-${name}-${version}`;
            },
        }
    },
    plugins: [
        new CleanPlugin('./dist', {
            verbose: false,
        }),
    ]
}

Для справки функция getPackageJson выглядит следующим образом:

function getPackageJson(context) {
    do {
        const packageJson = `${context}\\package.json`;
        if (fs.existsSync(packageJson)) { return require(packageJson); }
        const splits = context.split(/\\/);
        splits.pop();
        context = splits.length > 0 ? splits.join('\\') : undefined;
    } while (context);
    return undefined;
}

Я установил три тестовых плагина, 1используя d3 v5.9.1, а остальные 2 оба используют d3 v3.5.17.Используя эту конфигурацию, я могу правильно связать подключаемые модули и их зависимости по отдельности, я создал тестовый сервер для обслуживания связанных входных пакетов и пакетов зависимостей.Плагин 1, использующий d3 v5.9.1, похоже, работает нормально, но плагин 2 и плагин 3 никогда не работают вместе;один из них всегда будет неопределенным, когда я попытаюсь получить доступ к имени плагина (указанному в свойстве output.library).

Для справки, вот страница index.html:

<!DOCTYPE html>
<html>

<head>
    <script src="./vendors-d3-3.5.17.js" type="text/javascript"></script>
    <script src="./vendors-d3-5.9.1.js" type="text/javascript"></script>
    <script src="./plugin1.js" type="text/javascript"></script>
    <script src="./plugin2.js" type="text/javascript"></script>
    <script src="./plugin3.js" type="text/javascript"></script>
</head>

<body></body>

</html>

Index.js автоматически добавляется HtmlWebpackPlugin, который я использую (я использую webpack-dev-server для проверки этого).

Страница index.js, которая является тестовой страницей для этого,:

setTimeout(function () {
    plugin1.run();
    plugin2.run();
    plugin3.run();
}, 1000);

Плагин 1 Файл index.js выглядит следующим образом:

import * as d3 from 'd3';

export function run() {
    console.log('plugin1', !!d3.scaleLinear, !!(d3.scale || {}).linear);
}

Плагин 2 и 3 имеет этот файл index.js:

import * as d3 from 'd3';

export function run() {
    console.log('pluginX', !!d3.scale.linear, !!d3.scaleLinear);
}

Вывод консоли должен выглядеть следующим образом:

plugin1 true false
plugin2 true false
plugin3 true false

Но на самом деле я получаю либо:

plugin1 true false
plugin2 true false
Uncaught TypeError: Cannot read property 'run' of undefined

, либо это:

plugin1 true false
Uncaught TypeError: Cannot read property 'run' of undefined

Потому что либо plugin2, либо plugin3 (всегда только один из них) всегда неопределен.

Я подозреваю, что это как-то связано с загрузочным кодом, который вставляет веб-пакет, но я не могу быть на 100% уверен в этом.

...