Мне нужно настроить способ обработки импорта в моем приложении веб-пакетом.
Некоторые из моих сервисов имеют фиктивные реализации. В тестовом режиме я хочу импортировать фиктивный файл вместо реального сервиса, если рядом с сервисом существует файл с постфиксом «.mock», в противном случае импортирую сам сервис.
Обратите внимание, что мне нужны разные файлы вывода (main.js и test.js). Поэтому мне нужно убедиться, что test.js не включает реальные реализации сервисов (недостаточно предотвращения выполнения, исходный код не следует импортировать вообще).
Папка служб содержит следующие файлы:
service-1.js
service-1.mock.js
service-2.js
index.js
services / index.js:
import service1 from ‘./service-1’
import service2 from ‘./service-2’
export {service1, service2}
Посоветуйте, пожалуйста, как мне настроить свой веб-пакет.
@PatrickHund, чтобы убедиться, что все посетители могут понять мою ситуацию, я объяснил свою проблему более простым способом, однако, похоже, я не был таким успешным, лол. На самом деле это не связано с запуском тестов. Я хочу иметь разные файлы вывода для настольных и мобильных устройств с .desktop и .mobile в качестве дополнительных постфиксов для моих исходных файлов.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Согласно комментариям, я могу предложить эти обходные пути с помощью пользовательского загрузчика:
Создайте по одному .mobile и .desktop для каждого из ваших компонентов в основном файле (например, component.js, component.mobile.js, component.desktop.js) и используйте этот пользовательский загрузчик:
const targets = {
desktop: 'desktop',
mobile: 'mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import Header from './shared/Header';
import Footer from './shared/about';
import Categories from './category/categories';
// rest of code
`;
const manipulated = manipulateSource(source, targets.mobile, ['components', 'shared']);
console.info(manipulated);
function manipulateSource(src, target = targets.desktop, pathMatches = []) {
const paths = pathMatches.length ? `(${pathMatches.join('|')})` : '';
const pattern = new RegExp(`(?<left>.*import.*${paths}.*\\/)(?<name>[\\w\\-_]*)(?<rest>.*\\n)`, 'g');
const manipulated = src.replace(pattern, (...args) => {
const [{
left,
name,
rest
}] = args.slice(-1);
return `${left}${name}.${target}${rest}`;
});
return manipulated;
}Поскольку эти файлы имеют разные реализации для .mobile и .desktop, создайте третий файл (или четвертый, если вы хотите поместить общий код в основной файл) с тем же именем и значимым расширением (например: component.platformAdaptive.js), который можно обрабатывать с помощью regular expresion (или любого другого другой способ манипуляции). В этом методе вам может потребоваться поместить базовую реализацию в последний файл, если вы используете strongTypes (например, Typescript):
const targets = {
desktop: 'desktop',
mobile: 'mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import Header from './shared/Header.platformAdaptive';
import Footer from './shared/about.platformAdaptive';
import Categories from './category/categories.platformAdaptive';
// rest of code
`;
const manipulatedMob = manipulateSource(source, 'platformAdaptive', targets.mobile);
const manipulatedDesk = manipulateSource(source, 'platformAdaptive');
console.info(manipulatedMob);
console.info(manipulatedDesk);
function manipulateSource(src, replace, target = targets.desktop) {
const pattern = new RegExp(`(?<left>.*\\/)(?<name>[\\w\\-_]*\.)${replace}(?<rest>.*\\n)`, 'g');
const manipulated = src.replace(pattern, (...args) => {
const [{
left,
name,
rest
}] = args.slice(-1);
return `${left}${name}${target}${rest}`;
});
return manipulated;
}Оба вышеуказанных метода имеют некоторые ограничения при импорте, например, вы не можете использовать Barrel files (index.js), поскольку они предполагают, что последний фрагмент импорта является файлом компонента.
В этом случае вы можете добавить несколько папок с barrel для обработки этого импорта. например, во втором методе вам понадобится такая структура:
|-- components.platformAdaptive
|-- index.js
|-- components.mobile
|-- index.js
|-- components.desktop
|-- index.js
Или вы можете использовать / вместо . для создания вложенной структуры (например, components/platformAdaptive):
|-- components
|-- [+] platformAdaptive
|-- [+] mobile
|-- [+] desktop
Другой способ справиться с этой ситуацией - иметь разные классы с разными именами. Например, компонент List с различными реализациями для мобильных устройств и настольных ПК, тогда будет три компонента, таких как ListPlatformAdaptive, ListMobile, ListDesktop, в которых ListPlatformAdaptive может иметь базовые реализации, и barrel в папке компонентов, которая экспортирует компоненты:
import * as ListPlatformAdaptive from './list.platformAdaptive';
import * as ListMobile from './list.mobile';
import * as ListDesktop from './list.desktop';
export {
ListPlatformAdaptive,
ListMobile,
ListDesktop
}
Структура будет такой:
|-- components
|-- list.platformAdaptive.js
|-- list.mobile.js
|-- list.desktop.js
|-- index.js
Тогда манипуляция будет такой:
const targets = {
desktop: 'Desktop',
mobile: 'Mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import HeaderPlatformAdaptive as Header from './shared/Header';
import FooterPlatformAdaptive as Footer from './shared/about';
import CategoriesPlatformAdaptive as Categories from './category/categories';
// rest of code
`;
const replace = 'PlatformAdaptive';
const manipulatedMob = manipulateSource(source, replace, targets.mobile);
const manipulatedDesk = manipulateSource(source, replace);
console.info(manipulatedMob);
console.info(manipulatedDesk);
function manipulateSource(src, replace, target = targets.desktop) {
const pattern = new RegExp(replace, 'g');
const manipulated = src.replace(pattern, target);
return manipulated;
}При использовании этого метода вы должны быть осторожны с файлами barrel, которые должны быть исключены, и обратная сторона этого метода заключается в том, что все компоненты уже импортированы, поэтому стоимость импорта неприемлема.
Другой способ, который я могу придумать, - это добавить несколько примечаний в качестве комментария и отреагировать на его существование в этой строке:
const targets = {
desktop: 'Desktop',
mobile: 'Mobile'
};
const source = `
import Home from './components/home';
import About from './components/about';
import Header from './shared/Header'; /* @adaptive */
import Footer from './shared/about'; /* @adaptive: Desktop */
import Categories from './category/categories'; /* @adaptive: Mobile */
// rest of code
`;
const manipulatedMob = manipulateSource(source, targets.mobile);
const manipulatedDesk = manipulateSource(source);
console.info(manipulatedMob);
console.info(manipulatedDesk);
function manipulateSource(src, targetDevice = targets.desktop) {
const pattern = /(?<left>.*import\s+)(?<name>\w+)(?<rest1>.*)\@adaptive(\:\s*(?<target>\w+))?(?<rest2>.*)/g
const manipulated = src.replace(pattern, (matched, ...args) => {
let [{
left,
name,
rest1,
target,
rest2
}] = args.slice(-1);
target = target || targetDevice;
return target == targetDevice ?
`${left}${name}${target}$ as ${name}${rest1}${rest2}` :
matched;
});
return manipulated;
}В этом методе, таком как метод № 2, имена импортированных компонентов отличаются от оригинальных, но сопоставлены с оригинальным именем, что совсем не подходит, но мне это нравится больше всего, поскольку при использовании его в файлах barrel можно изменить адрес импортированного файла. Еще одна интересная часть может заключаться в передаче адреса целевых файлов относительно target device и его синтаксическом анализе.
Как видите, все мои ответы касались источников дескрипторов без проверки существования файла и предположения, что разработчик в этом уверен. Кстати, вы можете выполнить поиск, чтобы узнать, есть ли способ найти абсолютный путь к файлу, а затем проверить наличие целевых заменителей.
Какую среду тестирования вы используете? Jasmine, Mocha, Jest и т. д. - у большинства из них есть способы справиться с подобными проблемами. Я не думаю, что изменение webpack здесь - правильный подход.