Компания
130,59
рейтинг
5 декабря 2016 в 07:59

Разработка → React, Web Components, Angular и jQuery — друзья навеки. Универсальные JavaScript-компоненты tutorial

image
Эта статья о том, как написать универсальный JavaScript-компонент, который можно будет использовать


  • как React-компонент;
  • как Preact-компонент;
  • как Angular-компонент;
  • как Web Component;
  • как jQuery функцию для рендеринга в DOMElement;
  • как нативную функцию для рендеринга в DOMElement.

Зачем и кому это нужно


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


Как все будет реализовано


  1. Напишем React-компонент.
  2. Используя JavaScript-библиотеки preact и preact-compat, которые вместе работают точно так же как React и при этом весят жалкие 20 килобайт, напишем обертки для всего остального.
  3. Настроим сборку с помощью Webpack-а.

Пишем код компонента


Для примера разработаем Donut Chart такого вида:


Donut Chart


Здесь ничего удивительного мы не увидим — просто код.


import React from 'react';

export default class DonutChart extends React.Component {
    render() {
        const { radius, holeSize, text, value, total, backgroundColor, valueColor } = this.props;
        const r = radius * (1 - (1 - holeSize)/2);
        const width = radius * (1 - holeSize);
        const circumference = 2 * Math.PI * r;
        const strokeDasharray = ((value * circumference) / total) + ' ' + circumference;
        const transform = 'rotate(-90 ' + radius + ',' + radius + ')';
        const fontSize = r * holeSize * 0.6;
        return (
            <div style = {{ textAlign: 'center', fontFamily: 'sans-serif' }}>
                <svg width = {radius * 2 + 'px'} height = {radius * 2 + 'px'}>
                    <circle 
                        r = {r + 'px'} cx = {radius + 'px'} cy = {radius + 'px'}
                        transform = {transform} fill = 'none'
                        stroke = {backgroundColor} strokeWidth = {width}
                    />
                    <circle
                        r = {r + 'px'} cx = {radius + 'px'} cy = {radius + 'px'}
                        transform = {transform} fill = 'none'
                        stroke = {valueColor} strokeWidth = {width}
                        strokeDasharray = {strokeDasharray}
                    />
                    <text
                        x = {radius + 'px'} y = {radius + 'px' }dy = {fontSize/3 + 'px'}
                        textAnchor = 'middle' fill = {valueColor} fontSize = {fontSize + 'px'}
                    >
                        {~~(value * 1000 / total) / 10}%
                    </text>
                </svg>
                <div style = {{ marginTop: '10px' }}>
                    {text}
                </div>
            </div>
        );
    }
}

DonutChart.defaultProps = {
    holeSize : 0.8,
    radius : 65,
    backgroundColor : '#d1d8e7',
    valueColor : '#49649f'
};

Что должно получиться в итоге


Codepen Collection


Настраиваем сборку Webpack-ом


Базовый Webpack-конфиг
var webpack = require('webpack');

module.exports = {
    output: {
        path: './dist'
    },
    resolve: {
        extensions: ['', '.js'],
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: [
                        'latest',
                        'stage-0',
                        'react'
                    ],
                    plugins: [
                        'transform-react-remove-prop-types',
                        'transform-react-constant-elements'
                    ]
                }
            }
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': "'production'"
        }),
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.AggressiveMergingPlugin(),
        new webpack.optimize.UglifyJsPlugin({
            compress: { warnings: false },
            comments: false,
            sourceMap: true,
            mangle: true,
            minimize: true
        })
    ]
};

Добавляем в package.json скрипты для сборки проекта

"scripts": {
    "build:preact": "node ./scripts/build-as-preact-component.js",
    "build:react": "node ./scripts/build-as-react-component.js",
    "build:webcomponent": "node ./scripts/build-as-web-component.js",
    "build:vanila": "node ./scripts/build-as-vanila-component.js",
    "build:jquery": "node ./scripts/build-as-jquery-component",
    "build:angular": "node ./scripts/build-as-angular-component",
    "build": "npm run build:preact && npm run build:react && npm run build:webcomponent && npm run build:vanila && npm run build:jquery && npm run build:angular"
  }

Сборка Webpack-ом и обертка для Web Components


Модификация базового Webpack-конфига и сборка
var webpack = require('webpack');
var config = require('./webpack.config');
var statsConfig = require('./statsConfig');

config.resolve.alias = {
    'react': 'preact-compat',
    'react-dom': 'preact-compat'
};
config.entry = './src/DonutChartWebComponent.js';
config.output.filename = 'DonutChartWebComponent.js';

webpack(config).run(function (err, stats) {
    console.log(stats.toString(statsConfig));
});

Обертка


import React from 'react';
import ReactDOM from 'react-dom';
import DonutChart from './DonutChart';

const proto = Object.create(HTMLElement.prototype, {
    attachedCallback: {
        value: function() {
            const mountPoint = document.createElement('span');
            this.createShadowRoot().appendChild(mountPoint);
            const props = {
                radius          : +this.getAttribute('radius') || undefined,
                holeSize        : +this.getAttribute('hole-size') || undefined,
                text            : this.getAttribute('text') || undefined,
                value           : +this.getAttribute('value') || undefined,
                total           : +this.getAttribute('total') || undefined,
                backgroundColor : this.getAttribute('background-color') || undefined,
                valueColor      : this.getAttribute('value-color') || undefined
            };
            ReactDOM.render((
                <DonutChart {...props}/>
            ), mountPoint);
        }
    }
});
document.registerElement('donut-chart', {prototype: proto});

Пример использования


<donut-chart value="39.6" total="100" text="Hello Web Components"></donut-chart>

Результат



Сборка Webpack-ом и обертка для Angular


Модификация базового Webpack-конфига и сборка
var webpack = require('webpack');
var config = require('./webpack.config');
var statsConfig = require('./statsConfig');

config.resolve.alias = {
    'react': 'preact-compat',
    'react-dom': 'preact-compat'
};
config.entry = './src/DonutChartAngularComponent.js';
config.output.filename = 'DonutChartAngularComponent.js';
config.output.library = 'DonutChart';
config.output.libraryTarget = 'umd';

webpack(config).run(function (err, stats) {
    console.log(stats.toString(statsConfig));
});

Обертка


import React from 'react';
import ReactDOM from 'react-dom';
import DonutChart from './DonutChart';

const module = angular.module('future-charts-example', []);

module.directive('donutChart', function() {
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            const props = {
                radius          : +attrs['radius'] || undefined,
                holeSize        : +attrs['hole-size'] || undefined,
                text            : attrs['text'] || undefined,
                value           : +attrs['value'] || undefined,
                total           : +attrs['total'] || undefined,
                backgroundColor : attrs['background-color'] || undefined,
                valueColor      : attrs['value-color'] || undefined
            };
            ReactDOM.render((
                <DonutChart {...props}/>
            ), element[0]);
        }
    };
});

Пример использования


<body ng-app="future-charts-example">
    <donut-chart value="89.6" total="100" text="Hello Angular"></donut-chart>
</body>

Результат



Сборка Webpack-ом и обертка для jQuery


Модификация базового Webpack-конфига и сборка
var webpack = require('webpack');
var config = require('./webpack.config');
var statsConfig = require('./statsConfig');

config.resolve.alias = {
    'react': 'preact-compat',
    'react-dom': 'preact-compat'
};
config.entry = './src/DonutChartJQueryComponent.js';
config.output.filename = 'DonutChartJQueryComponent.js';
config.output.library = 'DonutChart';
config.output.libraryTarget = 'umd';

webpack(config).run(function (err, stats) {
    console.log(stats.toString(statsConfig));
});

Обертка


import React from 'react';
import ReactDOM from 'react-dom';
import DonutChart from './DonutChart';

jQuery.fn.extend({
    DonutChart: function(props) {
        this.each(
            function () {
                ReactDOM.render((
                    <DonutChart {...props}/>
                ), this);
            }
        );
    }
});

Пример использования


$('#app').DonutChart({
    value : 42.1,
    total : 100,
    text : 'Hello jQuery'
});

Результат



Сборка Webpack-ом и обертка для VanilaJS (использование из нативной функции)


Модификация базового Webpack-конфига и сборка
var webpack = require('webpack');
var config = require('./webpack.config');
var statsConfig = require('./statsConfig');

config.resolve.alias = {
    'react': 'preact-compat',
    'react-dom': 'preact-compat'
};
config.entry = './src/DonutChartVanilaComponent.js';
config.output.filename = 'DonutChartVanilaComponent.js';
config.output.library = 'DonutChart';
config.output.libraryTarget = 'umd';

webpack(config).run(function (err, stats) {
    console.log(stats.toString(statsConfig));
});

Обертка


import React from 'react';
import ReactDOM from 'react-dom';
import DonutChart from './DonutChart';

module.exports = function DonutChartVanilaComponent(mountPoint, props) {
    ReactDOM.render((
        <DonutChart {...props}/>
    ), mountPoint);
};

Пример использования


DonutChart(document.getElementById('app'), {
    value : 57.4,
    total : 100,
    text : 'Hello Vanila'
});

Результат



Сборка Webpack-ом для React


Модификация базового Webpack-конфига и сборка
var webpack = require('webpack');
var config = require('./webpack.config');
var statsConfig = require('./statsConfig');

var react = {
    root: 'React',
    commonjs2: 'react',
    commonjs: 'react'
};

var reactDom = {
    root: 'ReactDOM',
    commonjs2: 'react-dom',
    commonjs: 'react-dom'
};

config.externals = {
    'react': react,
    'react-dom': reactDom
};
config.entry = './src/DonutChartUMD.js';
config.output.filename = 'DonutChartReact.js';
config.output.library = 'DonutChart';
config.output.libraryTarget = 'umd';

webpack(config).run(function (err, stats) {
    console.log(stats.toString(statsConfig));
});

Результат



Сборка Webpack-ом для Preact


Модификация базового Webpack-конфига и сборка
var webpack = require('webpack');
var config = require('./webpack.config');
var statsConfig = require('./statsConfig');

var preactCompat = {
    root: 'preactCompat',
    commonjs2: 'preact-compat',
    commonjs: 'preact-compat'
};

config.externals = {
    'react': preactCompat,
    'react-dom': preactCompat
};
config.entry = './src/DonutChartUMD.js';
config.output.filename = 'DonutChartPreact.js';
config.output.library = 'DonutChart';
config.output.libraryTarget = 'umd';

webpack(config).run(function (err, stats) {
    console.log(stats.toString(statsConfig));
});

Результат



Заключение


Сколько в итоге будет весить каждый из вариантов:


React Preact VanilaJS jQuery Angular Web Components
Код компонента (3кб) Код компонента (3кб) Код компонента (3кб) Код компонента (3кб) Код компонента (3кб) Код компонента (3кб)
Обертка (1кб) Обертка(1кб) Обертка(1кб) Обертка (1кб)
preact.min.js (3кб) preact.min.js (3кб) preact.min.js (3кб) preact.min.js (3кб)
preact-compat.min.js (18кб) preact-compat.min.js (18кб) preact-compat.min.js (18кб) preact-compat.min.js (18кб)
3кб 3кб 25кб 25кб 25кб 25кб

Оверхед в 20 килобайт за возможность использовать React-компоненты в любых других фреймворках или в качестве Web Components — это прекрасный результат. Если вы разрабатываете какие-то React-компоненты, знайте — вы можете сделать их доступными всем и каждому — это очень просто. Надеюсь, что этот туториал поможет сделать мир хотя бы чуточку лучше и сократит страшную фрагментацию вселенной JavaScript-разработки.


Исходники: Github, Codepen, NPM

Автор: @MrCheater

Комментарии (53)

  • 0
    А что насчет биндинга в ангуляре?
  • +5
    Не думаю, что разработчики на ангуляре будут с неистовством мешать в проекты компоненты написанные на реакте. Разумнее было бы написать компонент на ваниле и адаптировать под конкретный фреймворк или библиотеку.
    • +6

      Писать на VanilaJS, вручную отслеживать изменение состояния компонента, самостоятельно управлять перерисовкой всего и вся внутри — дело непростое. Требуется гораздно больше кода и времени на его поддержку.
      Представьте, например, что есть библиотека с чартами, которая работает по принципу, описанному в статье — так почему бы ее не использовать в проекте, если она хорошая. Какая разница программисту, что там внутри, если она работает и много килобайт не отжирает.

  • +1

    Мне всегда казалось что использование Web Components единственное решение, которое на 100% совместимо с чем угодно другим. Зачем ещё кучу всего сверху?

    • +8

      На данный момент нативно Web Components очень мало где поддерживается
      custom-elements


      C полифилами ситуация лучше


      With the polyfills
      Но полифилы отжирают ~120 кб.


      И опять же — в Web Components — внутри все DOM-операции и отслеживание изменений состояния компонента нужно делать ручками, что не так удобно, как в React. Уровень абстракции другой

      • 0

        React нативно вообще нигде не поддерживается и не будет.


        Уровень абстракции не хуже. При использовании Polymer есть и биндинги, и возможности рендерить кучу элементов из массива по шаблону, включая реакцию на изменение состояния (в новом проекте я использую Redux вместе с веб-компонентами), и декларативные подписки на события, и многое другое.


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


        В противовес попробуйте интегрировать один React компонент в не-React проект — у вас и оверхед React будет похуже оверхеда полифиллов + Polymer, да и без трехэтажной системы сборки не обойтись. А веб-компоненты просто работают. В совершенно любом проекте, так же как в любом проекте работает <div>.

        • +2
          В противовес попробуйте интегрировать один React компонент в не-React проект — у вас и оверхед React будет похуже оверхеда полифиллов + Polymer

          В статье я показал, как добиться оверхеда в 20кб.

          • +3

            x-tags, к примеру, тоже 20 КБ, а в браузерах что поддерживают нативно будет вообще 0 (как не крути, таких подавляющее большинство).
            При этом будет быстрее и проще, ибо используются нативные интерфейсы.

          • 0
            Присоединяюсь к предыдущему комментатору. Polymer 2.0 больше не является фреймворком — теперь это библиотека с сахаром для нативных компонентов + привязка данных. Полимер, таким образом, можно вывести в зависимость через html imports — сколько бы не было на странице компонентов, ссылающихся на него, свои N килобайт он загрузит только один раз.

            В описанном способе (насколько я понял) технологический оверхед зашит в каждый компонент, так что 8 компонентов на одной странице по 25 килобайт каждый — это уже солидный жирок. Поправьте, если я ошибаюсь
            • +3
              так что 8 компонентов на одной странице по 25 килобайт каждый

              Я предполагаю, что разработчик компонентов даст вам эти 8 компонентов, собранных в одну либу вместе с одним preact-ом.


              @salex772 предложил вариант получше https://habrahabr.ru/company/devexpress/blog/316358/?reply_to=9946908#comment_9946898
              Я думаю, это вполне реально реализовать

              • +2
                Я предполагаю, что разработчик компонентов даст вам эти 8 компонентов, собранных в одну либу вместе с одним preact-ом.

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

                Я думаю, это вполне реально реализовать

                Вот тут, да, хотя все равно выглядит сложнее нативного компонента + html imports.
        • +2
          React нативно вообще нигде не поддерживается и не будет.
          При использовании Polymer

          Изначально речь шла о нативных веб-компонентах. Polymer — это тоже фреймворк и тоже поставляется отдельно от браузера, а значит, сколько-то весит.


          Дальше — выбор, на каком фреймворке строить внутренности компонента, это уже дело личных предпочтений каждого, и React (Preact) тут тоже хороший вариант

        • 0
          В чем конкретно будет оверхед? В условной загрузке 20кб? Это только первый раз, после этого все это будет в кэше броузера.
      • 0
        Только полифилы можно загружать по надобности.
  • +1
    Оверхед в 20 килобайт......- это прекрасный результат.

    нда, на моем первом компьютере 48К было, из них 8 — на видео память и сиcтемные переменные уходило…
    эх…
  • +5
    Как говорится смешивать, но не взбалтывать.
    Из своего опыта знаю, что лучше наоборот писать компоненты или какие-то не большие библиотеки на VanilaJS. А для фреймворков писать уже адапторы, если это необходимо.

    Хотя ваша мысль мне то де нравится, но как и с любыми решениями такого рода, наверняка есть свои подводные камни.
  • +3
    Хороший способ, но хотелось бы подробностей про дополнительный вес оберток и его масштабирование. Во сколько килобайт превратится оверхед в 22КБ на один компонент скажем для 10, 30 или 100 компонент? Какая часть этих 22КБ может быть общая? Просто если там общих 21КБ из 22КБ, то это одно, а если 12КБ, то другое.
    • 0

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


      Пример PropTypes

      DonutChart.propTypes = {
      radius: React.PropTypes.number.isRequired,
      holeSize: React.PropTypes.number.isRequired, //0...1
      text: React.PropTypes.string.isRequired,
      value: React.PropTypes.number.isRequired,
      total: React.PropTypes.number.isRequired,
      backgroundColor: React.PropTypes.string.isRequired,
      valueColor: React.PropTypes.string.isRequired
      };


      Тогда 100 компонентов (вес их React-овского кода) + 20кб (preact + preact-compat) + десяток килобайт на код, который соберает налету обертки из PropTypes для любого компонента

  • 0
    Я так думаю, что неплохо было вынести preact в externals и подключать динамически через scriptJs в зависимости от того, есть ли внешние библиотеки в window. Не обязательно для каждого компонента тянуть свой реакт.
    • 0

      Про дублирование Preact-а на каждый компонент речи не идёт. Если 100 компонентов в сборке будет — то получится 100 компонентов + один Preact

      • 0
        А если один, то webpack включит его в сборку, при этом на странице он уже может быть в составе другого компонента вне вашей сборки… Я уверен, preact или react надо делать внешним компонентом и тянуть его опционально, если его там нет.
        • 0

          Возможно вы и правы, но как реализовать динамическую подгрузку preact-а, чтобы компонент не успел до этого поломаться из-за ReferenceError это еще нужно серьезно подумать

          • +1
            Ну я бы сделал через сторонний загрузчик — это первое что должно исполнятся внутри UMD модуля. Например scriptjs, Он проверит зависимости, скачает что надо пл CDN, вернет промис, на resolve() которого нужно повесить инициализацию реакта. К моменту инициализации компонента все ссылки уже должны быть удовлетворены.
          • +3

            А чем плох webpack конфиг externals. Можно задать его как-то так (на примере react):


            externals: {
                'react': {
                    root: 'React',
                    commonjs2: 'react',
                    commonjs: 'react',
                    amd: 'react'
                }
            }

            в итоге потребитель может использовать несколько подобных универсальных библиотек от разных авторов и никакого дублирования preact. И для обёрток в 1 кб можно для тех же целей, оформить отельную библиотеку.

            • 0

              Лично мне бы не хотелось заставлять программиста, который использует мою библиотеку, подключать какие-то react/preact-ы. Ибо это детали реализации уже.
              Но предложенный вами вариант тоже имеет место быть. Многим он подойдет

              • 0

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

            • 0
              Externals просто говорит о том, что это все «в другом месте». А речь про то, как это все подключить помимо сборки, я и предложил использовать загрузчики типа LABjs или ScriptJS
  • 0
    А что с управлением состоянием? Просто все очень хорошо с реюзом пока у компонентов не появится внутреннего состояния, а вам не понадобится history management.
    • 0

      Внутри компонента может быть свой state, свое внутреннее локальное состояние, которое никуда не денется, пока экземпляр компонента не будет уничтожен.
      Если же компонент будет переодически уничтожаться и создаваться заново, и нужно чтобы данные не пропадали, или какой-то другой сложный сценарий использования компонента — тогда придется вынести состояние еще куда-то, но сделать это можно.

      • 0
        на каком-нибудь легаси сайте на каждой странице компонент будет уничтожаться и создаваться каждый раз, ИМХО при обновлении state нужна сериализация каждый раз.
        • 0

          Компонент можно написать так, чтобы он поддерживал помимо uncontrolled режима, в котором state внутри создается, еще и controlled режим, при котором state не нужен. В controlled режиме компонент будет дергать колбеки, они будут менять state и отдавать его обратно в props (в аргументы). Так что никакой сериализации. Просто данные можно хранить вне компонента, если нужно

          • +1
            Да, согласен, так лучше будет. А и сам стараюсь сверху передавать колбеки и и обрабатывать их на уровне контейнера.
  • 0
    Я правильно понимаю что при таком коде
    <svg width = {radius * 2 + 'px'} height = {radius * 2 + 'px'}>
    у вас вся шаблонизация будет проходить на клиенте?
    • 0
      При желании вы можете делать всю или часть шаблонизации на клиенте.
      Что именно вас интересует?
  • +1

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


    Кроме того, почему вы не пользуетесь возможностями CSS? Например, мне нужен такой же компонент, но с перла заливкой внутри круга.

    • 0

      В Web Components огромные заморочки с настоящим CSS, поэтому я его не использовал. Но всегда можно взять что-то из аттрибутов(props) и на основе этого выставить style у нужных элементов. Внутри Shadow DOM там как-то не так CSS работает, я мало с этим работал — особо не подскажу.


      Насчет микромодулей/микрофреймворка — для меня важна совместимость с React, так что это не мой путь. И я готов заплатить за него 20 лишними килобайтами

      • 0

        Почему вам так важен React?

        • 0

          React меня устраивает больше, чем любой другой фреймворк для UI из тех, что я пробовал. Но это просто дело вкуса.

          • 0

            А какие фреймворки вы пробовали?

            • 0

              То, что пробовал для написания UI — jquery, ember, angular (чутка), react и еще пару велосипедных. Не так уж и много — но с react-ом я ощущаю наименьшее количество боли при разработке

              • 0

                Но всё же некоторая боль есть? В чём она заключается?

    • 0

      А можно какой-нибудь пример такого фреймворка? Просто 20 килобайт — это и так вроде не много, но если можно ещё меньше, то почему нет.

      • 0

        Пример — preact весит всего 3кб. Умеет почти всё тоже самое, что и React, но нет Context-а. Если нужен Context, то подойдёт preact + preact-compat

        • 0

          Это же просто хитрый шаблонизатор, а не фреймворк.

          • 0
            React сам по себе не фреймворк.
            • 0

              Однако диктует сомнительные ограничения архитектуры, что несколько печалит.

              • 0
                Какие ограничения? По сути всё, что он делает — инкапсулирует и скрывает работу c DOM.
                • 0

                  Половинчатое скрытие работы с домом (события вполне себе нативные со всеми вытекающими).
                  Обновление через формирование целого поддерева, вместо точечных обновлений.
                  Формирование данных для всего поддерева при каждом обновлении, вместо обновления лишь тех данных, что зависят от исходных.
                  Смешивание декларативного и императивного описания визуализации.

                  • 0
                    События браузера оборачиваются в SyntheticEvent.

                    Необходимые обновления вычисляются внутри библиотеки, на архитектуре приложения это как сказывается?

                    Если вы про то, что тело метода render компонента пишется как return , то никто вас не заставляет использовать jsx. Если про что-то другое, то поясните мысль, пожалуйста.
                    • 0
                      События браузера оборачиваются в SyntheticEvent.

                      Всё равно из него берут target и пошло поехало.


                      Если вы про то, что тело метода render компонента пишется как return, то никто вас не заставляет использовать jsx.

                      Без него всё совсем страшненько становится.


                      Необходимые обновления вычисляются внутри библиотеки, на архитектуре приложения это как сказывается?

                      Виртуальный дом генерируется заново каждый раз.

                      • 0
                        Всё равно из него берут target и пошло поехало.

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

                        Это деталь реализации библиотеки, на архитектуру приложения она влиять не должна.

                        • 0

                          Сомнительные ограничения — это сомнительно. Проблема половинчатой абстракции именно в половинчатости. Она вносит дополнительную сложность, не давая бонусов от полной абстракции.


                          Не должна, но влияет, потому как:


                          1. Если не учитывать детали реализации приложение начинает тупить.
                          2. Невозможно применить некоторые классные архитектурные приёмы. Например — ленивая загрузка и обработка данных.
      • 0

        Можно, только осторожно.


        Я попробовал собрать donut, но там получается всё вместе в минифициованном виде 20 кб, что не сильно лучше варианта с преактом. Но тут и компонент очень простой без особых зависимостей.

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

Самое читаемое Разработка