Добавить Автора
задний план
По мере роста проекта одна страницаspaПостепенно включает множество направлений бизнеса
- Система торговых центров
- Система послепродажного обслуживания
- Система членства
- ...
Когда страница проекта превышает определенное количество (150+), возникает ряд проблем.
- Масштабируемость
Время компиляции проекта (запуск сервера, изменение кода) становится все больше и больше, и каждая отладка может быть сосредоточена только на 1 или 2 страницах.
- противоречивые потребности
Все требования находятся в текущем git, а тестовая среда часто ставится в очередь из-за слишком большого количества требований.
Исходя из вышеперечисленных проблем, существуют технические требования к разделению git. детали следующим образом
Цель
- еще
spa
Поскольку улучшение — это среда разработки, мы, конечно, не хотим дробить проект, чтобы повлиять на пользовательский опыт. Если бизнес-направление полностью разделено на две отдельные страницы, пользователи больше не смогут плавно переключаться между бизнес-направлениями, потому что все фреймворки и статические ресурсы будут перезагружаться при переключении страниц. Поэтому при переходе на бизнес-линию необходимо оставаться в спа-центре.
不刷新页面, поделиться одной и той же записью страницы;
- Бизнес-страницы больше не загружают ресурсы повторно
Поскольку большинству направлений бизнеса необходимо использовать структуру (
vue,vuex...), общедоступные компоненты (dialog,toast) уже загружены на входе spa, и я не хочу, чтобы бизнес-линия загружала эти ресурсы повторно. Бизнес-проекты должны содержать только собственные уникальные ресурсы и иметь возможность использовать общедоступные ресурсы;
- Полное распределение ресурсов между бизнес-направлениями
Бизнес-линии должны иметь возможность использовать маршрутизатор для перехода друг к другу и иметь доступ к другим бизнес-линиям, включая глобальный магазин.
Требования такие же, как и выше, а метод реализации описан ниже.
техническая база
- vue: 2.4.2
- vue-router: 2.7.0
- vuex: 2.5.0
- webpack: 4.7.0
выполнить
Предположим, вы хотите отделить направление деятельности от основного проекта.helloпублично заявить
- Основной проект: Содержит основные страницы системы + различные необходимые фреймворки (vue, vuex...)
- hello project: содержит собственный внутренний бизнес-код hello
Перейти к процессу страницы приветствия
- Пользователь посещает бизнес-страницу Маршрутизация
#/hello/index; - Роутер основного проекта не подобран, перейти в паблик
*иметь дело с; - Публичный маршрутизатор определяет, что текущий маршрут является маршрутом приветствия бизнес-линии, и запрашивает запись приветствия.
bundle js; - Во время выполнения приветственной записи js зарегистрируйте собственный маршрутизатор и сохраните его в основном проекте;
- После завершения регистрации отметьте текущую бизнес-линию hello как зарегистрированную;
- Затем маршрут вызывает следующий. Он будет автоматически продолжать запрашивать страницу, соответствующую #/hello/index.
chunk(js, css) успешный переход на страницу; - На данный момент hello интегрирован с основным проектом, hello может свободно использовать все магазины и использовать маршрутизатор для свободного перехода на любую страницу. Готово
Это функции, которые вам нужны.Давайте рассмотрим конкретную реализацию шаг за шагом.
Запрос бизнес-маршрутизации (шаг 1)
первый запрос#/hello/indexВ настоящее время все маршруты в маршрутизаторе не могут быть сопоставлены и станут общедоступными.*иметь дело с
/** 主项目 **/
const router = new VueRouter({
routes: [
...
// 不同路由默认跳转链接不同
{
path: '*',
async beforeEnter(to, from, next) {
// 业务线拦截
let isService = await service.handle(to, from, next);
// 非业务线页面,走默认处理
if(!isService) {
next('/error');
}
}
}
]
});
Инициализация направления бизнеса (шаг 2, шаг 3)
Во-первых, требуется глобальная конфигурация бизнес-линии для хранения входных js-файлов каждой бизнес-линии.
const config = {
"hello": {
"src": [
"http://local.aaa.com:7000/dist/dev/js/hellobundle.js"
]
},
"其他业务线": {...}
}
В настоящее время вам необходимо использовать конфигурацию бизнес-линии, чтобы определить, принадлежит ли текущий маршрут бизнес-линии.Если это так, запросите бизнес-линию вместо возврата false.
/** 主项目 **/
// 业务线接入处理
export const handle = async (to, from, next) => {
let path = to.path || "";
let paths = path.split('/');
let serviceName = paths[1];
let cfg = config[serviceName];
// 非业务线路由
if(!cfg) {
return false;
}
// 该业务线已经加载
if(cfg.loaded) {
next();
return true;
}
for(var i=0; i<cfg.src.length; i++) {
await loadScript(cfg.src[i]);
}
cfg.loaded = true;
next(to); // 继续请求页面
return true;
}
Несколько замечаний
- Общая конфигурация бизнес-линии хранится в бэкэнде, который указан здесь для иллюстрации.
- Направление бизнеса загружается только один раз,
loadedдля условия суда. Если загружено, переходите непосредственно к следующему - Когда первая линия бизнеса успешно загружена, основной проект уже содержит
#/hello/indexмаршрут, то следующий может прыгать нормально. См. следующий раздел по причинам
Работа, проделанная записью hello entry.js (шаг 4)
В целях экономии ресурсов линия hello business больше не упаковывается повторно.vue,vuexи т.д. В основном проекте загружен фреймворк.
Затем, чтобы hello работал правильно, основной проект должен передать указанный выше фреймворк в hello, напрямую повесив соответствующие переменные вwindow:
/** 主项目 **/
import Vue from 'vue';
import { default as globalRouter } from 'app/router.js'; 2个需要动态赋值
import { default as globalStore } from 'app/vuex/index.js';
import Vuex from 'vuex'
// 挂载业务线数据
function registerApp(appName, {
store,
router
}) {
if(router) {
globalRouter.addRoutes(router);
}
if(store) {
globalStore.registerModule(appName, Object.assign(store, {
namespaced: true
}));
}
}
window.bapp = Object.assign(window.bapp || {}, {
Vue,
Vuex,
router: globalRouter,
store: globalStore,
util: {
registerApp
}
});
УведомлениеregisterAppЭтот метод — это метод монтирования, который интегрирует hello с основным проектом и вызывается бизнес-линией.
На предыдущем шаге entry.js из hello запускался нормально, поэтому давайте посмотрим, что делает hello в entry:
/** hello **/
import App from 'app/pages/Hello.vue'; // 路由器根实例
import {APP_NAME} from 'app/utils/global';
import store from 'app/vuex/index';
let router = [{
path: `/${APP_NAME}`,
name: 'hello',
meta: {
title: '页面测试',
needLogin: true
},
component: App,
children: [
{
path: 'index',
name: 'hello-index',
meta: {
title: '商品列表'
},
component: resolve => require.ensure([], () => resolve(require('app/pages/goods/Goods.vue').default), 'hello-goods')
},
{
path: 'newreq',
name: 'hello-newreq',
meta: {
title: '新品页面'
},
component: resolve => require.ensure([], () => resolve(require('app/pages/newreq/List.vue').default), 'hello-newreq')
},
]
}]
window.bapp && bapp.util.registerApp(APP_NAME, {router, store});
Несколько замечаний
-
APP_NAMEЭто уникальный идентификатор бизнес-линии, то есть привет - Направления бизнеса имеют свои внутренние
routerа такжеstore - Активная линия деловых звонков
registerApp, интегрируйте собственный роутер и магазин с основным проектом - Когда магазин интегрирован, его нужно добавить
namespace: true, потому что в это время весь магазин линии hello business стал модулем globalStore -
addRoutesа такжеregisterModuleЭто метод динамической регистрации маршрутизатора и хранилища. - разгромлен
nameдолжен быть уникальным для основного проекта
Обновление конфигурации бизнес-направления
Конфигурация бизнес-линии должна быть обновлена после завершения каждого компиляции Hello. Обновление разделено на本地调试更新а также线上更新.
-
本地调试更新Просто нужно обновить локальный файл конфигурацииservice-line-config.json, а затем файл читается основным проектом и возвращается в js при запросе бизнес-конфигурации. -
线上更新Это проще, после каждого релиза и компиляции обновлять полный url текущей записи js+md5 на бэкэнд
выше, см. использованиеwebpack-pluginБолее подходящая для текущей сцены реализация выглядит следующим образом
class ServiceUpdatePlugin {
constructor(options) {
this.options = options;
this.runCount = 0;
}
// 更新本地配置文件
updateLocalConfig({srcs}) {
....
}
// 更新线上配置文件
uploadOnlineConfig({files}) {
....
}
apply(compiler) {
// 调试环境:编译完毕,修改本地文件
if(process.env.NODE_ENV === 'dev') {
// 本地调试没有md5值,不需要每次刷新
compiler.hooks.done.tap('ServiceUpdatePlugin', (stats) => {
if(this.runCount > 0) {
return;
}
let assets = stats.compilation.assets;
let publicPath = stats.compilation.options.output.publicPath;
let js = Object.keys(assets).filter(item => {
// 过滤入口文件
return item.startsWith('js/');
}).map(path => `${publicPath}${path}`);
this.updateLocalConfig({srcs: js});
this.runCount++;
});
}
// 发布环境:上传完毕,请求后端修改
else {
compiler.hooks.uploaded.tap('ServiceUpdatePlugin', (upFiles) => {
let entries = upFiles.filter(file => {
return file &&
file.endsWith('js') &&
file.includes('js/');
});
this.uploadOnlineConfig({files: entries});
return;
})
}
}
}
Уведомление,uploadedСобытие генерируется подключаемым модулем загрузки статических ресурсов нашей проектной группы, и оно передает полный путь ко всем загружаемым в данный момент файлам. Вам нужно дождаться загрузки файла в CDN, прежде чем обновлять бизнес-линию.
Затем используйте его в веб-пакете
/** hello **/
{
...
plugins: [
// 业务线js md5更新
new McServiceUpdatePlugin({
app_name,
configFile: path.resolve(process.cwd(), '../mainProject/app/service-line-config.json')
})
],
...
}
Обратите внимание, что при локальной отладке бизнес-конфигурация主项目будет использоваться только, поэтому непосредственно обновите файл конфигурации в главном каталоге проекта
Отладочный выпуск
На основе вышеуказанного плагина есть следующие эффекты
Процесс отладки выглядит следующим образом:
- Запустите основной сервер проекта (порт
7777); - Запустите сервер hello business line (порт
7000), в это время успешный запуск одновременно обновит локальный файлservice-line-config.json; - Посетите страницу приветствия, загрузите локальную конфигурацию, загрузите
7000Статические ресурсы, предоставляемые портом (например, http://local.aaa.com:7000/dist/dev/js/hellobundle.js)
Процесс тестирования выпуска следующим образом:
- воплощать в жизнь
npm run test - В процессе выполнения файл будет загружен, а бизнес-конфигурация тестовой среды будет обновлена.
- На данный момент доступ к странице тестовой среды обновлен.
Видно, что hello-релиз более легковесный, чем основной проект, потому что бизнес-линия обновляет только интерфейс, а основному проекту нужно обновить html-веб-сервис для выпуска.
резюме
На данный момент первоначальные основные требования выполнены.После доступа к странице бизнес-направления страница бизнес-направления будет объединена с главной страницей проекта, чтобы сформировать новый спа-центр, а внутреннее хранилище спа-центра и маршрутизатора будут полностью общими.
Видно, что в основном используется метод динамической регистрации семейства vue. Ниже приведены некоторые проблемы, возникающие в процессе, и пути их решения.
Возникшие проблемы и решения
Wepback упаковка линии hello business
- Направления бизнеса требуют отдельных пространств имен пакетов
- Для того, чтобы отличить его от основного проекта, он будет приветствовать бизнес-линию
bundleПереименовано, добавлен префикс названия компании - Чем меньше входных файлов, тем лучше, поэтому удалена некоторая конфигурация упаковки.
- удален
vendor: основная сторонняя библиотека загружается основным проектом - удален
dll: ресурсы dll загружаются основным проектом - Удалена среда выполнения(
manifest) конфигурация: каждое направление бизнеса будет обрабатывать загрузку зависимостей отдельно
- удален
/** hello **/
{
...
entry: {
[app_name + 'bundle']: path.resolve(SRC, `entry.js`)
},
output: {
publicPath: `http://local.aaa.com:${PORT}${devDefine.publicPath}`,
library: app_name // 业务线命名空间
},
...
optimization: {
runtimeChunk: false, // 依赖处理与bundle合并
splitChunks: {
cacheGroups: false // 业务线不分包
}
},
...
}
УведомлениеlibraryНастройки изолируют отдельные направления бизнеса
входной файл
полагаться
проблема разделения роутера
Первоначально используйте /:name для публичной обработки.
Однако обнаружено, что приоритет маршрутизатора находится в порядке вставки массива, тогда приоритет вставленного позднее маршрута hello всегда будет ниже, чем маршрут /:name.
использовать после*Выполнение публичной обработки всегда будет в сухом остатке, и проблема будет решена.
разделение магазина
Хранилище hello зарегистрировано как модуль globalStore и должно быть помеченоnamespaced: true, иначе данные будут недоступны;
В магазине используется один и тот же базовый и основной проект:
/** hello **/
let { Vuex } = bapp;
// 全局store获取
let { mapState: gmapState, mapActions: gmapActions, createNamespacedHelpers } = Vuex;
// 本业务线store获取
const { mapState, mapActions } = createNamespacedHelpers(`${APP_NAME}/feedback`)
export default {
...
computed: {
...gmapState('userInfo', {
userName: state => state.userName
}),
...gmapState('hello/feedback', {
helloName2: state => state.helloName
}),
...mapState({
helloName: state => state.helloName
})
},
}
разделение интерфейса
Несмотря на то, что интерфейсный проект разделен, внутренний интерфейс по-прежнему использует одно и то же доменное имя, поэтому общедоступный метод для генерации параметров интерфейса может быть доступен для приветствия, а затем организован самим приветствием.
общественное использование
Вы можете использовать глобальный напрямую组件,mixins,directives, который можно использовать напрямуюfont.
Локальный связанный контент должен быть скопирован в hello или открыт для hello, прежде чем его можно будет использовать.
Изображение вообще нельзя использовать повторно
локальный серверный инструмент
Основной проект должен иметь относительно хорошую работу с запросом, поэтому он реализован нами.expressдля отладки локально.
Но единственная функция проекта hello — предоставлять локальные текущие js и css, поэтому используйте официальныйdevServerдостаточно.
выше, спасибо за чтение
Оригинальная ссылка:Фирменные блюда Овощи сливы Талант/деталь/75,Вы также можете найти апплет "Техническая группа по продуктам Meicai" в WeChat. Он полон галантерейных товаров и обновляется каждую неделю. Если вы хотите изучить технологии, не пропустите его.