У меня есть требование создать 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% уверен в этом.