Как создать модульное клиентское / серверное приложение с разными кодовыми базами (часть JS)? - PullRequest
0 голосов
/ 09 мая 2018

В настоящее время мы начинаем перестраивать нашу CMS. У нас хороший опыт работы с VueJS. Однако оно не станет полноценным одностраничным приложением VueJS, поскольку мы пока не можем избавиться от файлов рендеринга на стороне сервера (JSP).

Проблема в том, что CMS не находится в 1 кодовой базе. Мы используем примерно следующую структуру:

Основы CMS (в отдельном репозитории git)

  • Модуль: управление пользователями
  • Модуль: управление контентом
  • и т.д.

Дополнительные модули

  • Информационный бюллетень (в отдельном репозитории)
  • Формы (в отдельном хранилище)

Это все модули Maven, которые мы используем в нескольких проектах для клиентов. Мы не всегда используем все модули. Мы добавляем модули, которые используем в качестве зависимости в Maven «проект клиента» (для полноты: в pom.xml проекта).

Структура проекта (в отдельном репозитории)

  • Dep # 1
  • Dep # 2
  • Специальный клиентский модуль
  • и т.д.

Наше предпочтение для клиентской части / JS заключается в использовании классов Typescript компонентов VueJS (наш собственный пользовательский код) и, конечно, внешних библиотек (с узлом / пряжей в качестве менеджера зависимостей).

Сейчас я провел исследование по импорту / модулям ES6, но пока не решен / не решен следующий вопрос:

CMS будет содержать несколько сборочных пакетов, таких как:

  • generic.js (например, код для отображения модальных сообщений / предупреждений и т. Д.) связанный JS-файл, содержащий классы сборки Typescript / компоненты vue и т. Д.
  • content-manament.js (в зависимости от библиотек generic.js)
  • и т.д.

Модуль новостной рассылки будет содержать пакет сборки: newsletter.js (в зависимости от библиотек generic.js)

Пользовательский проект также будет содержать модули с зависимостями от классов в generic.js

В идеале я бы хотел собрать комплекты отдельно. Такие как:

  • generic.js (встроенный пакет - содержит все более узкие библиотеки ниже)
  • messages.ts
  • dialogs.ts
  • cms.js
  • newsletter.js
  • таможенно-клиент-module.js

А в newsletter.js я бы хотел использовать классы из generic.js, такие как:

import {messages} from "????";

messages.alert('Alert text');

Я пока не вижу, как лучше всего решить эту проблему. Возможно, я думаю, что слишком сложно, но надеюсь, что у одного из вас есть хорошая отправная точка.

Заранее спасибо!

1 Ответ

0 голосов
/ 09 мая 2018

Вы можете использовать Webpack с Разделение кода

Существует три основных подхода к разбиению кода:

  • Точки входа: разделение кода вручную с использованием конфигурации входа.
  • Предотвращение дублирования: используйте SplitChunksPlugin для дедупликации и разделения фрагментов.
  • Динамический импорт: разделение кода с помощью вызовов встроенных функций внутри модулей.

Предполагая, что модули высокого уровня (cms.js, newsletter.js, ...) независимы друг от друга и зависят только от generic.js

Папка strcuture

src/
├── cms/
│   ├── index.ts
│   ├── ...
├── newsletter/
│   ├── index.ts
│   ├── ...
└── generics/
    ├── index.ts
    ├── messages.ts
    ├── dialogs.ts

SRC / генерики / dialogs.ts

export function open(title: string) {
    console.log('Opening dialog : ', title);
}

SRC / генерики / messages.ts

export function alert(msg: string) {
    console.log('alert : ', msg);
}

SRC / генерики / index.ts

import * as m from './messages';
import * as d from './dialogs';

export let messages = m ;
export let dialogs = d;

ЦСИ / К / index.ts

import { dialogs, messages } from '../generics';

messages.alert('CMS started ...');

ЦСИ / бюллетень / index.ts

import { dialogs, messages } from '../generics';

messages.alert('Newsletter started ...');

Разделение кода в Webpack

1. Точки входа

Это, безусловно, самый простой и интуитивно понятный способ разделения кода. Тем не менее, это больше руководство и есть некоторые подводные камни.

Итак, в вашем конфигурационном файле вам нужно будет вручную объявить ваши модули, используя объект entry:

// webpack.config.js
const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
        'newsletter': './src/newsletter/index.ts',
        'cms': './src/cms/index.ts',
    },
    module: {
        rules: [
        {
            test: /\.ts?$/,
            use: 'ts-loader',
            exclude: /node_modules/
        }
        ]
    },
    resolve: {
        extensions: [ '.ts', '.js' ]
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: "dist/",
    }
};

С этим конфигом у вас будет два модуля в папке dist:

               Asset      Size      Chunks             Chunk Names
       cms.bundle.js   4.6 KiB         cms  [emitted]  cms
newsletter.bundle.js  4.64 KiB  newsletter  [emitted]  newsletter

Поскольку модули cms и newsletter зависят от модуля generics, этот модуль связан (скопирован) с ними.

2. Предотвратить дублирование с помощью SplitChunksPlugin

Добавьте конфигурацию optimization.splitChunks в файл webpack.config.js:

optimization: {
    splitChunks: {
        chunks: 'all',
        minChunks: 1,
        name: 'generics',
        minSize: 10,
    }
}

Теперь модуль generics находится в своем собственном блоке (не забудьте включить его в HTML-файл), и сборка сгенерирует 3 файла:

               Asset      Size      Chunks             Chunk Names
       cms.bundle.js  5.85 KiB         cms  [emitted]  cms
  generics.bundle.js  1.61 KiB    generics  [emitted]  generics
newsletter.bundle.js   5.9 KiB  newsletter  [emitted]  newsletter 

3. Динамический импорт

Измените src/cms/index.ts для использования динамического импорта:

import(/* webpackChunkName: "generics" */ '../generics').then(generics => {
    console.log('Generics module loaded ...');
    generics.messages.alert('CMS started ...');
});

Измените src/newsletter/index.ts для использования динамического импорта:

import(/* webpackChunkName: "generics" */ '../generics').then(generics => {
    console.log('Generics module loaded ...');
    generics.messages.alert('Newsletter started ...');
});

Вам также придется изменить некоторые параметры компиляции Typescript (и, возможно, установить polyfill для Promise):

"module": "esnext",
"lib": [
    "es2015"
]   

Теперь вам не нужно включать модуль generics в ваш HTML-файл. Когда import() выполняется, Webpack извлекает модуль generics с сервера и кэширует его.

Надеюсь, это поможет вам начать:)

Редактировать (ответ на комментарий):

Если модули находятся в отдельных проектах. Вы будете использовать npm или yarn для управления зависимостями. Например, в package.json проекта newsletter вы добавите generics как зависимость.

Теперь вы должны использовать не относительные пути для вашего импорта. Так, например, динамический код импорта будет:

import(/* webpackChunkName: "generics" */ 'generics').then(generics => {
    console.log('Generics module loaded ...');
    generics.messages.alert('Newsletter started ...');
});

Если вы хотите связать весь свой код, вы можете добавить модуль main. Этот модуль будет иметь зависимости от всех других модулей. Затем в index.ts этих модулей импортируйте все остальные модули. Этот index.ts должен быть точкой входа в конфигурацию Webpack.

Имейте в виду, что объединение всей вашей кодовой базы в один файл в большинстве случаев не рекомендуется для больших одностраничных приложений, поскольку оно может легко получить более 8 МБ. Рекомендованная производительность Webpack по умолчанию составляет ~ 250 КБ на файл.

...