Рубрики
Без рубрики

Происходит изоморфный с Python и реагировать

Написание изоморфных веб-приложений с React и Python без необходимости в Nodejs или WebPack. Помечено с Python, React, Web, активами.

Изоморфные веб-приложения являются приложениями, часть или весь код выполнены как на сервере, так и на клиенте. Сервер и браузер разделяют часть или весь код.

Одним из самых больших целей, которые могут достичь изоморфных растворов, является улучшение SEO для приложений для одной страницы, но до сих пор такие функции были в основном доступны для разработчиков JavaScript, которые могут запустить тот же код на браузере и Nodejs.

Поскольку браузеры поддерживают только JavaScript (если esoteric Technologies не участвуют) все широко распространенные библиотеки и каркасы, доступные для создания изоморфных приложений, ожидают запуска на JavaScript и как разработчик Python, мы были в значительной степени выбора.

Быть недовольным этой ситуацией, это то, что привело меня к работе на Дукпи , библиотека Python, которая направлена на удаление потребности в Nodejs от моей рабочей набора инструментов (надеюсь, что она будет для других людей).

Один из самых распространенных изоморфных веб-каркасов – Реагировать , который позволяет представлять собой сервер React Componts и прикрепить их динамическое поведение, когда они достигнут браузера.

Несколько месяцев назад я написал короткую статью на Как использовать ES2015 и JSX в веб-приложениях Python без необходимости в ноде или webassets.

Но он не охватил, как может быть создано изоморфное приложение, код JavaScript приложения все еще работал в браузере, и компоненты React не могут предоставить предварительно отображать версию. Поэтому я решил запустить эту статью, которая демонстрирует как использовать Dukpy и реагировать вместе, чтобы написать изоморфное веб-приложение с Python, даже не устанавливая NODEJS.

Если вы еще не прочитали его, убедитесь, что посмотрите на статью ES2015, так как этот потребуется как должное, что понятия, объясненные там уже известны.

Я возьму как должное, что у вас уже есть все необходимые пакеты Python, установленные как Showcased в ES2015 Статья :

$ pip install TurboGears2
$ pip install Kajiki
$ pip install tgext.webassets
$ pip install dukpy

Как только все необходимые части находятся, мы можем начать с того, что приложение, которое отображает компонент React на стороне клиента, то мы сделаем тот же компонент рендеринга на сервере и у вас есть браузер оттуда.

Для этого мы создадим Статика/js каталог, где мы поставим все наши JavaScript

$ mkdir statics
$ mkdir statics/js

Обязательно скачайте реагировать и React-Dom в этот каталог, чтобы они были доступны для нашего веб-приложения

$ cd statics/js
$ curl -O 'https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.js'
$ curl -O 'https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.js'

Последнее, но не менее важно нам нужен сам компонент, который будет простой Helloworld компонент. Наш компонент будет объявлен внутри Статика/js/helloworld.jsx файл:

export class HelloWorld extends React.Component {
  render() {
    return (
      
Hello {this.props.name}
); } }

Тогда мы создадим app.py Файл, в котором мы поставьте код Python, который запустит веб-сервер, создает веб-приложение, компилируйте JSX для простого JS и служить на странице индекса, которая сделает сам компонент:

import tg
from tg import AppConfig
from tg import TGController
from tg import expose
import kajiki

page = kajiki.XMLTemplate(u'''
    
    
      
''', mode='html5') class RootController(TGController): @expose() def index(self): return page(dict( g=tg.app_globals )).render() config = AppConfig(minimal=True, root_controller=RootController()) config.renderers = ['kajiki'] config.serve_static = True config.paths['static_files'] = 'statics' from webassets.filter import register_filter from dukpy.webassets import BabelJSX register_filter(BabelJSX) import tgext.webassets as wa wa.plugme( config, options={ 'babel_modules_loader': 'umd' }, bundles={ 'bundle.js': wa.Bundle( 'js/react.js', 'js/react-dom.js', wa.Bundle( 'js/HelloWorld.jsx', filters='babeljsx', ), output='assets/bundle.js' ) } ) application = config.make_wsgi_app() from wsgiref.simple_server import make_server print("Serving on port 8080...") httpd = make_server('', 8080, application) httpd.serve_forever()

Если вы попытаетесь запустить сохраненные app.py Файл с таким контентом, и все зависимости правильно на месте, вы должны увидеть что-то вроде:

$ python app.py
No handlers could be found for logger "tg.configuration.app_config"
Serving on port 8080...

Заговорим о вашем браузере на http://localhost: 8080 должен приветствовать вас с “Привет мир”

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

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

Это требует одного дополнительного компонента, нам придется скачать наши Статика/js. каталог, React-Dom-Server Библиотека, которая позволяет Сервер бокового рендеринга реагирования

$ cd statics/js
$ curl -O 'https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom-server.js'

Затем мы собираемся сделать наш компонент в нашу веб-приложение Python, чтобы сделать, чтобы мы собираемся полагаться на Dukpy для фактического рендеринга и веб-сайцесов для предоставления требуемых зависимостей

import json
from dukpy import JSInterpreter, jsx_compile
from markupsafe import Markup


class ReactRenderer(object):
    def __init__(self, jspath):
        self.jspath = jspath
        self.jsi = JSInterpreter()
        self.jsi.loader.register_path(self.jspath)
        self.components = {}
        self.initialized = False

    def _init(self):
        if self.initialized:
            return

        bundle_js = tg.app_globals.webassets['bundle.js']
        self.jsi.evaljs(
            [f.data() for f in bundle_js.build()] +
            ["var ReactDOM = require('react-dom-server');"]
        )
        self.initialized = True

    def render(self, component, **kwargs):
        self._init()
        code = "ReactDOM.renderToString(React.createElement({component}, {args}), null);".format(component=component, args=json.dumps(kwargs))
        return Markup(self.jsi.evaljs(code))

Reactrenderer это удобный класс, который создаст переводчик Dukpy с Реагировать и наше Helloworld Компонент предварительно загружен (через bundle.js webassets bundle мы уже объявили) и React-Dom-Server загружен через требовать

На самом деле класс состоит из одного Визуализация () Метод, который инициализирует интерпретатор (если он еще не инициализирован) и затем вытеснит указанный компонент React. Таким образом, мы можем использовать этот класс, чтобы сделать любой компонент, который был доступен в наше bundle.js в том числе HellowOrld One.

Только оставлена часть, мы должны создать его и предоставить ему наше Индекс () Действие, так что он может использовать его для оказания компонента. Для удобства и, как обычно, мне понадобится объект реакции, доступный везде, я сделаю его в конфигурации моего приложения

import os
config.react_renderer = ReactRenderer(
   os.path.join(os.path.dirname(__file__), 'statics', 'js')
)

Убедитесь, что вы добавляете эту строку перед созданием приложения Turbogears (так до make_wsgi_app ). Аргумент, предоставляемый на Reactrenderer, является путь, в котором он может найти любой дополнительный модуль JavaScript, который будет загружен через требовать в этом случае, как мы скачали React-Dom-Server в Статика/js. Это указанный путь. Теперь, когда наш реакстример на месте мы можем редактировать наши индекс действие и предоставить реактивный рендерер к нашему HTML-шаблону

class RootController(TGController):
    @expose()
    def index(self):
        return page(dict(
            render_react=tg.config['react_renderer'].render,
            g=tg.app_globals
        )).render()

Если вы правильно добавили Render_reaCt Значение для те, которые действие контроллера обеспечивает Страница Шаблон Теперь мы можем изменить сам шаблон, чтобы сделать компонент.

Если вы помните, у нас ранее было пустое Изомор девочка

что ДИД действовал только как цель для нашего Reactom.runder Вызов которого оказывает компонент и поместил его в Div.

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

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

${render_react('HelloWorld.HelloWorld', name='World')}

Render_reaCt Callable на самом деле Reactrender.runder Метод мы предоставили от действия. Если вы помните, что первый аргумент – это компонент, который должен быть отображен (в этом случае Helloworld от Helloworld Модуль) и любой дополнительный аргумент ключевого слова передан как свойство компонента. В этом случае мы предоставляем Имя = Мир Свойство (так же, как мы сделали в ract.createlement Call).

Обратите внимание, что действительно важно, чтобы любое свойство предоставленному компоненту при рендере из Python соответствует тем, которые предоставляются Rect.Createelement Вызов в JS или React будет жаловаться и заменит содержимое div вместо того, чтобы повторно использовать его (то же самое произойдет, если вы ошибочно поместите пустые пробелы до или после отображения визуализации).

Если все работало, как ожидалось, небольшой момент, когда ваша страница была пустой, должна исчезла. Компонент теперь сервер предварительно визуализируется Python и React будет просто ударить в браузере, продолжающемся, где осталось Python.

Поздравляю! Мы достигли нашего первого изоморфного применения в чистом Python!: D.

Гист для кода, используемого в этой статье, доступен на GitHub: https://gist.github.com/amol-/4563c7dc27c94d8ea58fabacb4cd71c6

Эта статья была первоначально опубликована на https://medium.com/@__amol__

Оригинал: “https://dev.to/__amol__/going-isomorphic-with-python-and-react”