В этой серии будет показан весь процесс от идеи до производства проекта Сапер. В этом введении объясняется, как настроить проект.

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

Если вы хотите сразу перейти к коду, вот ветка с кодом, разработанным в этой главе.

Идея

Несколько месяцев назад был выпущен PlayStation 5. С выпуском каждой новой консоли начали раздаваться разговоры о ее ретро-совместимости — возможности играть в игры с предыдущих консолей. Так пришла идея создать веб-сайт, управляемый сообществом, чтобы легко проверить, работает ли игра на недавно выпущенной PS5.

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

Целевая страница — это всегда хорошее начало.

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

Или сообщение о том, что совпадений нет, и возможность создать новую запись.

И, наконец, страница сведений, где пользователь может проголосовать, прокомментировать или написать новую запись.

Технологии

Когда наша концепция готова, пришло время решить, как мы воплотим ее в жизнь. В частности, какие технологии использовать. В данном случае технология предшествовала концепции. Я хотел разработать что-то с помощью Сапера, и это концепция, к которой я пришел. Sapper позаботится о внешнем интерфейсе, используя Svelte, и о бэкэнде, Node.js. Бэкэнд идет в Польке по умолчанию, но я переключил его на Экспресс, так как он мне больше знаком и у него большая поддержка.

Для стилизации Tailwind CSS дает нам несколько базовых инструментов и большую гибкость. Его легко использовать и строить. Это не библиотека компонентов, поэтому мы действительно можем адаптировать внешний вид нашего веб-сайта.

Для сохранения данных, поскольку мы получаем информацию, можно сказать, документы, и между ними не так много — вообще никаких — ссылок, лучше всего подходила база данных NoSQL. И MongoDB — одна из самых популярных среди них. А в качестве бонуса взаимодействие между Mongo и Express хорошо задокументировано и поддерживается с помощью Mongoose.

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

Мне нужно написать небольшую заметку о Саппере. В то время, когда я начал разработку этого проекта, у Sapper была версия 0.28, и все ждали выхода версии 1.0. Некоторое время спустя Рич Харрис, главный человек, стоящий за Svelte, сказал, что Sapper 1.0 никогда не будет выпущен в пользу SvelteKit. Вы можете прочитать об этом здесь".

Настройка

Первый шаг, закрепите наш проект. Sapper поставляется с хорошим шаблоном, который мы можем использовать.

npx degit "sveltejs/sapper-template#rollup" retro-ps5
cd retro-ps5
node scripts/setupTypeScript.js

Последний скрипт подготавливает проект к использованию TypeScript и добавляет sveltePreprocess, который заботится о его транспиляции. Он также позаботится о SCSS, если мы решим его использовать.

Мы можем указать, какой язык мы используем, с помощью атрибута lang.

<div>
    <h1>Hello, {world}!</h1>
</div>
<script lang="ts">
  let name = "world";
</script>
<style lang="scss">
    div {
        h1 {
            color: red;
        }
    }
</style>

Я также добавлю Prettier для форматирования моего кода. Мы можем установить плагин для работы с определенным форматированием Svelte, например, порядок блоков кода, стилей и шаблонов.

И в наш package.json добавляем следующие скрипты.

"format:check": "prettier --check .",
"format:write": "prettier --write ."

Как я упоминал ранее, Sapper по умолчанию поставляется с Polka, но я предпочитаю использовать Express.

yarn add express
yarn add --dev @types/express

А в server.ts переходим на Express.

const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

Если мы используем TypeScript, компилятор может пожаловаться, что обратный вызов ошибки имеет неявный тип any. Следуя этому ответу, мы можем исправить это как таковое.

app  
  .listen(PORT)
  .on('error', err => {
    if (err) console.error('error', err);
  })

Мы можем начать использовать Cypress таким образом.

yarn add --dev cypress
yarn run cypress open

Последняя команда создает папку cypress для наших тестов и заполняет ее примерами. Для более легкого доступа к нему мы можем добавить следующий скрипт в package.json.

"e2e": "cypress open"

Чтобы установить и настроить Tailwind CSS, я следовал этому руководству, в частности истории коммитов. Начнем с установки всех необходимых нам пакетов.

yarn add --dev "autoprefixer" "cssnano" "postcss" "postcss-import" "postcss-load-config" "postcss-nesting" "postcss-preset-env" "tailwindcss"
npx tailwindcss init -p

Последняя команда генерирует tailwind.config.js и postcss.config.js, которые мы заполняем следующим образом.

Затем в rollup.config.js добавляем

const preprocess = sveltePreprocess({ postcss: true,});
// and in the svelte plugin
svelte({
  dev,
  hydratable: true,
  emitCss: true,
  preprocess: [preprocess]
}),

Удаляем global.css, который идет с шаблоном, и его ссылку в template.html. Затем мы создаем src/global.pcss и src/components/GlobalStyle.svelte.

И, наконец, мы добавляем GlobalStyle к src/routes/_layout.svelte, что является основой, по которой следуют все маршруты — страницы загружаются внутри <slot /> — и меняем стиль в src/routes/index.svelte, чтобы использовать PostCSS и Tailwind CSS.

// _layout.svelte
<main>
  <GlobalStyle />
  <slot />
</main>
// index.svelte
<style lang="postcss">
  h1,
  figure,
  p {
    @apply text-center my-0 mx-auto;
  }
  h1 {
    @apply text-3xl uppercase font-bold m-0 mb-4 text-orange-500 font-sans;
  }
  figure {
    @apply m-0 mb-4;
  }
  img {
    @apply w-full max-w-5xl m-0 mb-4;
  }
  p {
    @apply my-0 mx-auto;
  }
  @screen md {
    h1 {
      @apply text-5xl;
    }
  }
</style>

При запуске нашего приложения иногда мы можем видеть ошибку Server is not listening on port 3000. Это останавливает живую перезагрузку нашего кода. Наиболее вероятная причина заключается в том, что время ожидания сервера истекло при попытке обработать весь CSS с помощью PostCSS. Другими причинами/решениями могут быть https://github.com/sveltejs/sapper/issues/730 и https://github.com/sveltejs/sapper/issues/431.

Для разработки самый простой путь — запустить образ Docker с MongoDB. Чтобы легко проверить состояние базы данных разработки, мы можем использовать образ mongo-express, чтобы иметь графический интерфейс.

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

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

yarn add mongoose
yarn add @types/mongoose --dev

Мы создаем нашу игровую модель в src/models и экспортируем ее с помощью функции connectDb в src/models/index.ts.

Мы добавляем useNewUrlParser и useUnifiedTopology, чтобы избежать следующих ошибок.

  (node:17808) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
  (node:17808) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.

В идеале мы хотим указать ссылку на базу данных, среди другой информации, через файл среды. Sapper не читает автоматически .env, поэтому мы используем dotenv для его чтения.

Мы создаем файл .env с любой информацией, которую хотим, добавляем ее в .gitignore, потому что мы не хотим передавать секреты в репозиторий, и используем их в server.ts для подключения к базе данных.

Это была долгая установка! Надеюсь, я не слишком вас утомил. В следующей части мы собираемся перейти к более интересному кодированию.

Вы можете увидеть весь код до этого момента в https://github.com/omirobarcelo/retro-ps5/tree/part0.

Спасибо, что дочитали до конца! Увидимся в следующей части!

Ссылки