Создание сайтов в Санкт-Петербурге. Встречайте Redwood, бессерверную платформу Jamstack с полным стеком

 
 

Представьте себе приложение React, доставляемое через CDN, которое отправляет запросы GraphQL на серверную часть с AWS Lambdas по всему миру, и все они доступны через файл git push. Это Redwood — самоуверенная полнофункциональная структура, включающая в себя Jamstack.

Redwood заполняет потребность, которую сообщество JavaScript отсутствовало в течение некоторого времени — непростая задача в экосистеме, где скорость появления новых инструментов сама по себе стала мемом. Это полнофункциональное JavaScript-решение предлагает фантастический опыт разработки, призванный привнести самоуверенную, основанную на шаблонах философию разработки Rails в быстрый и безопасный опыт, предлагаемый сайтами Jamstack.

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

Идеи, лежащие в основе фреймворка Redwood, воплощены в самом названии. Секвойи — тип дерева в Северной Калифорнии. Это большие деревья, самые высокие в мире, некоторые достигают 380 футов (около 116 метров). Самые старые из ныне живущих секвой появились около 3200 лет назад. Шишки сосны красного дерева на удивление маленькие. Деревья устойчивы к огню и издалека кажутся сложными, но вблизи остаются простыми. Это то, чего пытается достичь фреймворк — дать разработчикам возможность создавать красивые приложения, плотные, устойчивые и с которыми легко работать.

В этом уроке я подробно рассмотрю Редвуд и то, что он предлагает. Я предполагаю некоторое знакомство с React, GraphQL и Jamstack. Если вы хотите продолжить, вы можете найти весь код демо-примера на GitHub. В этом учебном пособии будет создано приложение CRUD (создание-чтение-обновление-удаление) и показано, как легко это сделать в Redwood.

Начальная настройка

Для успешной установки Redwood инструмент проверяет следующие требования к версии:

Узел: ≥12

Пряжа: ≥1,5

Предполагая, что Node доступен через NVM, например, установите Yarn через npm:

npm install -g yarn

Все команды Redwood используют Yarn, что является обязательным требованием. Чтобы запустить свое первое приложение:

yarn create redwood-appgetting-started-redwood-js

Вот как выглядит исходный вывод в терминале:

Первоначальный проект Редвуда

Убедитесь, что целевой каталог является новой или пустой папкой, иначе эта команда Yarn завершится ошибкой. Перейдите в этот новый каталог и запустите сервер разработки:

cd getting-started-redwood-js

yarn redwood dev

Та-да! Это автоматически открывает браузер с установленным расширением http: //localhost:8910. Ваш новый проект должен выглядеть так:

Первая страница Редвуда

Продолжайте и оставьте сервер разработки работающим. Я обязательно сообщу вам, когда потребуется перезагрузка. Затем, когда первоначальный проект Redwood готов, пришло время зафиксировать прогресс:

git init

git add.

git commit -m «First commit»

Не стесняйтесь ковыряться в скелетном проекте. Должен быть.gitignoreфайл, в который вы можете добавить любые файлы, которые хотите игнорировать. Например, исходный проект скелета имеет node_modulesпапку в этом файле. Все, что не находится в этом файле, фиксируется в репо.

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

Вернитесь и посмотрите на вывод консоли после запуска исходного проекта. Должно появиться сообщение «Просмотр файлов в api/src/functions». Это говорит о том, что любые изменения внутреннего кода автоматически обновляются с помощью этого средства просмотра файлов веб-пакета.

Структура папки Редвуд

Откройте проект Redwood в проводнике или в вашем любимом редакторе кода и посмотрите на структуру папок. Игнорируя несущественные файлы, он имеет следующую иерархию:

┣━┓ api

┃ ┣━┓ db

┃ ┃ ┣━━ schema.prisma

┃ ┃ ┗━━ seed.js

┃ ┗━┓ src

┃ ┣━┓ functions

┃ ┃ ┗━━ graphql.js

┃ ┣━━ graphql

┃ ┣━┓ lib

┃ ┃ ┗━━ db.js

┃ ┗━━ services

┗━┓ web

┣━┓ public

┃ ┣━━ favicon.png

┃ ┣━━ README.md

┃ ┗━━ robots.txt

┗━┓ src

┣━━ components

┣━━ layouts

┣━┓ pages

┃ ┣━┓ FatalErrorPage

┃ ┃ ┗━━ FatalErrorPage.js

┃ ┗━┓ NotFoundPage

┃ ┗━━ NotFoundPage.js

┣━━ index.css

┣━━ index.html

┣━━ index.js

┗━━ Routes.js

В корне находятся папки webи api, которые разделяют интерфейсный и внутренний код. Redwood называет их «сторонами», а Yarn называет их «рабочими пространствами».

Папка apiимеет следующие подкаталоги:

db, который содержит базу данных:

schema.prismaимеет определение схемы базы данных с таблицами и столбцами.

seed.jsизначально заполняет базу данных любыми данными нулевой конфигурации.

Миграции баз данных выполняются в SQLite и являются частью фреймворка. После того, как я добавлю базу данных, будет dev.dbфайл и папка с именем migrations. Вот как Redwood отслеживает изменения схемы базы данных в проекте.

srcимеет весь внутренний код:

functions: они будут иметь функции Lambda и graphql.jsфайл, сгенерированный Redwood.

graphql: это схема GraphQL, написанная на языке определения схемы (или SDL).

libимеет один файл db.js, который настраивает базу данных Prisma. Эта папка предназначена для кода, который не подходит для functionsили services.

services: это для бизнес-логики, которая работает с данными. Код, который запрашивает или изменяет данные, находится здесь.

Для внешнего интерфейса посмотрите в webкаталоге:

publicимеет все статические ресурсы, которых нет в React. Все файлы в этой папке копируются как есть:

favicon.png: значок, который появляется на вкладке браузера при первом открытии страницы.

robots.txtконтролирует поисковые роботы для поисковой оптимизации.

README.mdобъясняет, как и когда использовать эту общую папку.

srcимеет несколько подкаталогов:

componentsимеет традиционные компоненты React и ячейки Redwood (подробнее об этом позже).

layouts: HTML/компоненты, которые являются общими для Страниц. В проекте макеты необязательны.

pagesимеет компоненты, которые могут быть заключены в макеты и стать целевой страницей для URL-адресов. Например, /authorsсопоставляется с одной страницей, и каждый маршрут страницы имеет свою собственную папку.

NotFoundPage/NotFoundPage.js: фреймворк обслуживает эту страницу, когда страницы не существует (Routes.jsсм. ниже).

FatalErrorPage/FatalErrorPage.jsрендерит с исключением неперехваченной ошибки в приложении.

index.css: общее место для размещения глобального CSS, который больше нигде не используется.

index.html: Реагировать на начальную страницу.

index.js: загрузочный код для запуска приложения.

Routes.js: определения маршрута, которые сопоставляют URL-адрес со страницей.

В Routes.jsфайле приложение маршрутизируется к NotFoundPage:

 

Создание базы данных авторов

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

id: последовательный уникальный идентификатор для этого автора

name

topic: любимая тема автора

createdAt: метка времени для этой записи

Редвуд использует Prisma ClientJS для взаимодействия с базой данных через построитель запросов ORM. В клиенте Prisma есть еще один инструмент под названием Migrate, который последовательно обновляет схему базы данных. Каждое изменение схемы является миграцией, и Prisma Migrate создает ее для изменения базы данных. Prisma поддерживает большинство популярных разновидностей SQL, таких как SQLite, MySQL и PostgreSQL. В этом руководстве я буду ориентироваться на SQLite, чтобы упростить его.

Откройте api/db/schema.prismaи определите Authorтаблицу. Обязательно уничтожьте любой образец кода в этом файле, потому что он будет выполняться при миграции.

Например:

datasource DS {

provider = «sqlite»

url = env («DATABASE_URL»)

}

generator client {

provider = «prisma-client-js»

binaryTargets = «native»

}

model Author {

id Int @id @default (autoincrement ())

name String

email String @unique

topic String?

createdAt DateTime @default (now ())

}

Это определяет таблицу со следующими столбцами:

an id: Prisma использует @idдля построения отношений с другими таблицами, а @defaultзначение является последовательным autoincrement () значением.

определяется nameкак Stringтип

электронная почта, @uniqueопределенная какString

необязательный String? столбец с названием темы

столбец временной метки, createdAtустановленный DateTimeкак@defaultnow ()

Сделайте снимок этого как миграцию. Обязательно запустите эту команду Yarn в корне проекта:

yarn redwood db save create authors

Это создает миграцию под названием «создать авторов». Редвуду все равно, как называется, потому что это для других разработчиков. Когда это завершится, найдите новую папку api/db/migrationsс отметкой времени и именем для этой миграции. Вывод терминала будет иметь это имя и файлы, которые он сгенерировал. Моментальный снимок схемы находится в schema.prisma, а директивы для применения миграции — в steps.json.

Давайте теперь применим изменения базы данных:

yarn rw db up

Обратите внимание на использование сокращения rwвместо redwood.

Когда база данных обретает форму, пришло время перейти к пользовательскому интерфейсу. У Redwood есть строительные леса, позволяющие быстро получить базовое приложение CRUD:

yarn rw g scaffold author

Терминал выводит сгенерированные файлы для этого приложения. Если вы оставили сервер разработки работающим, обратите внимание, что браузер теперь указывает на ошибку 404 Not Found. Наведите браузер, http: //localhost:8910/authorsчтобы увидеть, что доступно:

Вот как выглядит каркас пользовательского интерфейса с CSS-скаффолдом. Если стиль отсутствует на странице, откройте index.jsи добавьте import '. /scaffold.css’:

Авторский эшафот

Скаффолд делает все поля в Authorтаблице обязательными, хотя тема является необязательным столбцом. Чтобы это исправить, откройте web/src/components/AuthorForm/AuthorForm.jsи замените тему TextFieldна эту:

<TextField

name="topic"

defaultValue={props.author?.topic}

className="rw-input"

/>

Чтобы увидеть Jamstack в действии, откройте инструменты разработчика в своем браузере и начните ковыряться. Я создам одного автора, используя свое имя без любимой темы (это необязательно). Затем обновите запись моей любимой темой. Сетевой трафик покажет запросы Ajax к серверной части, выполняющие всю работу без полного обновления страницы. Обязательно отключите кэш, чтобы увидеть весь сетевой трафик.

Вот так выглядит браузер:

Автор CRUD

Несколько замечаний. chunk.jsзапросы — это частичная загрузка страницы, которая отображает части приложения в браузере. Это React и веб-пакет в действии. Сетевые запросы JSON имеют полезную нагрузку GraphQL через POSTэтот запрос или изменяют данные в серверной части.

Открытие полезной нагрузки сетевого запроса показывает запрос GraphQL. Например:

{

«operationName»: «AUTHORS»,

«variables»: {},

«query»: «query AUTHORS {authors {id name email topic createdAt __typename}}»

}

Уф, так Редвуд создает все страницы с минимальным кодированием. Нет необходимости писать сложный компонент SQL или React с нуля. Вот что Редвуд имеет в виду под эшафотами.

Вот что сгенерировалось, когда я запустил yarn rw g scaffold authorкоманду:

файл SDL, который определяет несколько запросов и мутаций GraphQL вapi/src/graphql/authors.sdl.js

служебный файл api/src/services/authors/authors.js, который заставляет Prisma обращаться к базе данных

тестовый файл Jest api/src/services/authors/authors.test.jsдля написания модульных тестов (подробнее об этом чуть позже)

несколько страниц вweb/src/pages

EditAuthorPageредактировать автора

AuthorPageпоказать подробности об одном авторе

AuthorsPageчтобы получить всех авторов

NewAuthorPageсоздать автора

маршруты для этих страниц вweb/src/Routes.js

Макет в _web/src/layouts/AuthorsLayout/AuthorsLayout.js

клетки вweb/src/components

AuthorCellполучает одного автора

AuthorsCellполучает список авторов

EditAuthorCellполучает автор для редактирования в базе данных

компоненты также вweb/src/components

Author: показывает одного автора

AuthorForm: фактическая HTML-форма, используемая для изменения полей данных.

Authorsпоказывает список авторов

NewAuthorотображает форму для создания автора (редактирование использует ячейку)

Леса были достаточно круты, чтобы создать для меня тестовый файл, потому что Jest встроен в первоначальный проект. Взломайте services/authors/authors.test.jsи запустите пару юнит-тестов:

import { createAuthor, deleteAuthor } from '. /authors’

let author

it (‘creates an author’, () => {

author = createAuthor ({ input: { name: ‘T’, email: ‘xyz@abc.xo’ } })

})

it (‘deletes an author’, () => {

deleteAuthor (author)

})

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

Чтобы запустить тесты из корня проекта:

node_modules/.bin/jest

Как Redwood работает с данными

Redwood использует GraphQL для запроса и изменения данных. Вот что делает запрос GraphQL на серверной части:

Запрос красного дерева

Внешний интерфейс использует клиент Apollo для создания полезной нагрузки GraphQL, отправляемой в бессерверную функцию AWS Lambda в облаке. Если вы посмотрите на URL-адрес запроса в инструментах разработчика, обратите внимание, что все полезные нагрузки направляются в.redwood/functions/graphqlконечную точку. Файлы graphql/authors.sdl.jsи services/authors/authors.jsявляются интерфейсом к общедоступному API, доступному в Интернете.

Открытие api/src/graphql/authors.sdl.jsпоказывает следующее определение схемы GraphQL:

export const schema = gql`

type Author {

id: Int!

name: String!

email: String!

topic: String

createdAt: DateTime!

}

type Query {

authors: [Author! ]!

author (id: Int!): Author

}

input CreateAuthorInput {

name: String!

email: String!

topic: String

}

input UpdateAuthorInput {

name: String

email: String

topic: String

}

type Mutation {

createAuthor (input: CreateAuthorInput!): Author!

updateAuthor (id: Int!, input: UpdateAuthorInput!): Author!

deleteAuthor (id: Int!): Author!

}

`

Это означает, что Redwood ищет следующие пять преобразователей:

authors ()

author ({id})

createAuthor ({input})

updateAuthor ({id, input})

deleteAuthor ({id})

Crack open api/src/services/authors/author.js, который имеет следующий интерфейс:

import { db } from ‘src/lib/db’

export const authors = () => {

return db.author.findMany ()

}

export const author = ({ id }) => {

return db.author.findOne ({

where: { id },

})

}

export const createAuthor = ({ input }) => {

return db.author.create ({

data: input,

})

}

export const updateAuthor = ({ id, input }) => {

return db.author.update ({

data: input,

where: { id },

})

}

export const deleteAuthor = ({ id }) => {

return db.author.delete ({

where: { id },

})

}

Вернитесь и посмотрите на модульные тесты, которые я написал, потому что они повторно используют один и тот же код для доступа к базе данных. Redwood позволяет повторно использовать эти сервисы, поскольку они являются абстракциями над одной таблицей. Это означает, что бизнес-логика может повторно использовать как можно больше сервисов для выполнения работы. Часть этого функционально может быть представлена ​​клиенту через GraphQL или нет. Думайте об authors.sdl.jsопределении схемы GraphQL как о публичном интерфейсе, доступном для браузера, а об этом author.jsфайле — как о приватном интерфейсе. Чтобы доказать это, отредактируйте файл SDL и уничтожьте любую строку с мутацией — скажем, updateAuthor (). В следующий раз, когда полезная нагрузка GraphQL запрашивает это одно изменение, она взрывается в браузере. Довольно аккуратно, да?

Затем Redwood использует эту концепцию ячеек, чтобы сообщить Successкомпоненту, когда данные доступны. Теперь я углублюсь в ячейки, чтобы узнать, что это за Successкомпонент и что он делает.

Клетки

Хорошая новость заключается в том, что строительные леса уже заботятся о создании ячеек. Редвуд использует ячейки как декоративный подход к выборке данных. Используйте ячейки каждый раз, когда компонентам нужны данные из базы данных или для любых асинхронных вызовов с задержкой. Cells экспортирует несколько компонентов со специальными именами, например Success, а Redwood делает остальную работу.

Ячейки Редвуда следуют этому жизненному циклу при работе с данными:

выполнить QUERYи отобразить Loadingкомпонент

если есть ошибка, визуализируйте Failureкомпонент

если данных нет (нулевая конфигурация), визуализировать Emptyкомпонент

в противном случае визуализировать Successкомпонент

Существуют помощники жизненного цикла, например, beforeQueryдля обработки реквизитов перед запуском QUERY, а afterQueryтакже для обработки данных, возвращаемых из GraphQL. Эти помощники запускаются до того, как данные будут отправлены в Successкомпонент.

Как минимум клетки нужны QUERYи Successэкспортируются. Без Emptyкомпонента результаты заканчиваются в формате Success. Если компонента нет Failure, ошибки будут идти в консоль браузера.

Чтобы увидеть ячейку, откройте web/src/components/AuthorCell/AuthorCell.js:

export const QUERY = gql`

query FIND_AUTHOR_BY_ID ($id: Int!) {

author: author (id: $id) {

id

name

email

topic

createdAt

}

}

`

export const Loading = () =>

Loading...

 

export const Empty = () =>

Author not found

 

export const Success = ({ author }) => {

return ={author}>

}

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

Последние мысли

В целом, Redwood не готов к производству, но он требует много хороших концепций от сообщества JavaScript. Современные идеи, такие как React и GraphQL, поставили этот фреймворк на правильный путь. Ячейки решают распространенную проблему React, которую я слишком часто вижу при выборке данных. Работать с GraphQL и Prisma как с первоклассными гражданами с частными/общедоступными интерфейсами интересно. В качестве бонуса я был приятно удивлен, обнаружив, насколько легко писать модульные тесты в бэкенде.

3D-печать5GABC-анализAndroidAppleAppStoreAsusCall-центрChatGPTCRMDellDNSDrupalExcelFacebookFMCGGoogleHuaweiInstagramiPhoneLinkedInLinuxMagentoMicrosoftNvidiaOpenCartPlayStationPOS материалPPC-специалистRuTubeSamsungSEO-услугиSMMSnapchatSonyStarlinkTikTokTwitterUbuntuUp-saleViasatVPNWhatsAppWindowsWordPressXiaomiYouTubeZoomАвдеевкаАктивные продажиАкцияАлександровск ЛНРАлмазнаяАлчевскАмвросиевкаАнализ конкурентовАнализ продажАнтимерчандайзингАнтрацитАртемовскАртемовск ЛНРАссортиментная политикаБелгородБелицкоеБелозерскоеБердянскБизнес-идеи (стартапы)БрендБрянкаБукингВахрушевоВендорВидеоВикипедияВирусная рекламаВирусный маркетингВладивостокВнутренние продажиВнутренний маркетингВолгоградВолновахаВоронежГорловкаГорнякГорскоеДебальцевоДебиторкаДебиторская задолженностьДезинтермедитацияДзержинскДивизионная система управленияДизайнДимитровДирект-маркетингДисконтДистрибьюторДистрибьюцияДобропольеДокучаевскДоменДружковкаЕкатеринбургЕнакиевоЖдановкаЗапорожьеЗимогорьеЗолотоеЗоринскЗугрэсИжевскИловайскИрминоКазаньКалининградКировскКировскоеКомсомольскоеКонстантиновкаКонтент-маркетингКонтент-планКопирайтингКраматорскКрасноармейскКрасногоровкаКраснодарКраснодонКраснопартизанскКрасный ЛиманКрасный ЛучКременнаяКураховоКурскЛисичанскЛуганскЛутугиноМакеевкаМариупольМаркетингМаркетинговая информацияМаркетинговые исследованияМаркетинговый каналМаркетинг услугМаркетологМарьинкаМедиаМелекиноМелитопольМенеджментМерчандайзерМерчандайзингМиусинскМолодогвардейскМоскваМоспиноНижний НовгородНиколаевНиколаевкаНишевой маркетингНовоазовскНовогродовкаНоводружескНовосибирскНумерическая дистрибьюцияОдессаОмскОтдел маркетингаПартизанский маркетингПервомайскПеревальскПетровскоеПлата за кликПоисковая оптимизацияПопаснаяПравило ПаретоПривольеПрогнозирование продажПродвижение сайтов в ДонецкеПроизводство видеоПромоПромоушнПрямой маркетингРабота для маркетологаРабота для студентаРазработка приложенийРаспродажаРегиональные продажиРекламаРеклама на асфальтеРемаркетингРетро-бонусРибейтРитейлРовенькиРодинскоеРостов-на-ДонуРубежноеСамараСанкт-ПетербургСаратовСватовоСвердловскСветлодарскСвятогорскСевастопольСеверодонецкСеверскСедовоСейлз промоушнСелидовоСимферопольСинергияСколковоСлавянскСнежноеСоздание сайтов в ДонецкеСоледарСоциальные сетиСочиСтаробельскСтаробешевоСтахановСтимулирование сбытаСуходольскСчастьеТелемаркетингТельмановоТираспольТорговый представительТорезТрейд маркетингТрейд промоушнТюменьУглегорскУгледарУкраинскХабаровскХарцызскХерсонХостингЦелевая аудиторияЦифровой маркетингЧасов ЯрЧелябинскШахтерскЮжно-СахалинскЮнокоммунаровскЯндексЯсиноватая