Цель этой статьи — показать вам, как можно создать свой собственный статический персональный веб-сайт менее чем за 1 доллар в месяц. Я знаю, вы, наверное, думаете: «Я только что правильно прочитал?». Ты сделал! Конечно, есть предостережения по достижению этой цели, но в начале пути вашего веб-сайта размещение вашего собственного статического веб-сайта действительно должно стоить всего 0,01 доллара в месяц. Целевая аудитория этого поста — любой человек, имеющий некоторый опыт работы с JavaScript и общее представление о веб-разработке. Если у вас нет такого опыта, не переживайте! Я сделаю все возможное, чтобы объяснить идеи и концепции в этом посте, чтобы каждый мог им следовать!
Прежде чем мы начнем, давайте разберемся с некоторыми определениями, которые помогут нам понять различные термины, которые мы будем использовать при создании нашего первого сайта. Не стесняйтесь обращаться к этим определениям, когда мы проходим процесс добавления нашего сайта в Google Cloud:
В этой статье предполагается, что читатель имеет базовые знания в области разработки веб-сайтов и программирования. Я предполагаю, что у каждого читателя есть следующее:
Я склонен думать лучше, разбивая цель на поэтапные этапы работы. Давайте сформулируем наши задачи при создании нашего сайта следующим образом:
Если вы хотите создать свой собственный личный веб-сайт, для начала вам понадобится домен. Хотя изначально мы не будем его использовать, стоит сделать это сейчас, чтобы мы могли использовать собственный домен в следующей статье . Для меня моим доменом был afro-cloud.com , но вы действительно можете выбирать все, что приходит на ум, если у поставщика услуг регистрации есть доступный домен. Вы можете использовать несколько провайдеров регистрации доменов, я лично использовал GoDaddy, но здесь доступен подмножество вариантов (я не связан ни с одной из этих служб):
Теперь, когда мы настроили наш домен, давайте создадим учетную запись Google Cloud и включим выставление счетов.
Большой! Теперь, когда включена оплата, мы можем начать использовать сервисы Google Cloud. На данный момент у нас все готово с этой вкладкой, но мы вернемся к этой странице позже в статье, так что держите ее под рукой.
Если у вас возникли проблемы с выполнением действий, описанных в этой статье, свяжитесь с нами, и я сделаю все возможное, чтобы помочь устранить проблему. Хорошо, разобравшись с этим, продолжим. Мы будем использовать Next.js в отличие от других фреймворков React.js (или просто React) из-за их поддержки статического экспорта. Существует несколько различных вариантов развертывания для размещения приложения React.js, но я решил поделиться подходом Google Cloud Storage и Next.js из-за преимуществ SEO и экономии средств. При статическом экспорте Next.js при создании рабочей сборки для каждого маршрута создается файл HTML вместе со статическими ресурсами (файлами CSS и JS), которые соответствуют файлу HTML в отдельных фрагментах. Это важно, поскольку позволяет избежать загрузки ненужных пакетов JavaScript для просматриваемой страницы, что означает более быструю загрузку страницы. Все файлы, сгенерированные при запуске «следующей сборки», будут экспортированы в папку «out». Но об этом позже. Давайте создадим приложение.
Прежде всего, давайте установим на нашей машине стартовый проект Next.js. К счастью, в Next.js есть утилита create-next-app, такая же, как Create React App, для тех, кто ее использовал. Чтобы начать рабочий процесс, мы можем запустить следующую команду:
npx create-next-app@latest
Команда проведет нас через некоторые параметры конфигурации нашего проекта (вы можете выбирать все, что захотите; нам просто нужна генерация кода). Я выделил жирным шрифтом варианты, которые буду использовать в этой статье:
Отлично, теперь у нас есть код! Вы заметите, что наша папка node_modules заполнена, поэтому у нас установлены все зависимости, необходимые для запуска нашего приложения. В том же окне терминала, которое вы использовали для создания проекта, давайте выполним следующую команду: npm run dev . Это запустит рабочий процесс разработки Next.js, и мы сможем просмотреть наше приложение локально. Next.js предоставит URL-адрес для просмотра проекта на вашем компьютере. В большинстве случаев это будет http://localhost:3000 , но если у вас запущено другое веб-приложение, оно может выбрать другой порт, например 3001. При нажатии на ссылку вы должны увидеть что-то вроде следующего:
Хороший! У нас есть стартовое приложение, которое работает! Но давайте избавимся от стартовой страницы и приведем более классический пример «Hello World». Обновите файл src/app/page.tsx (или page.jsx), включив в него следующее:
import styles from "./page.module.css"; export default function Home() { return ( <main className={styles.main}> <div className={styles.description}> <p>Hello world!</p> </div> </main> ); }
Сохраните файл, вернитесь на вкладку браузера, где запущено наше приложение, и перезагрузите страницу. Вы должны увидеть «Hello world» на своем экране! Теперь давайте вернемся к работе статического экспорта. Нам нужно будет настроить файл next.config, чтобы включить эту функцию. Обновите объявление nextConfig следующим образом:
const nextConfig = { output: "export", };
Это даст команду Next.js в процессе сборки создавать отдельные HTML-файлы, соответствующие каждому маршруту в нашем приложении. На данный момент у нас есть только одна страница, поэтому давайте добавим еще одну страницу, чтобы проиллюстрировать преимущества статического экспорта. В каталоге app/ создайте новый каталог под названием «test». Во вновь созданном каталоге добавьте файл page.tsx (или page.jsx) и следующий код:
export default function Test() { return ( <main> <p>Hello test!</p> </main> ); }
Теперь, когда у нас есть тестовая страница, давайте добавим ссылку на нее с нашей домашней страницы. Откройте src/app/page.tsx (или page.jsx) и обновите файл, чтобы он выглядел так:
import Link from "next/link"; import styles from "./page.module.css"; export default function Home() { return ( <main className={styles.main}> <div className={styles.description}> <p>Hello world!</p> <Link href="/test">Test Page!</Link> </div> </main> ); }
Сохраните недавно обновленные файлы, вернитесь на вкладку браузера, в котором запущено наше приложение, и перезагрузите страницу. Вы должны увидеть новую ссылку с надписью «Тестовая страница!» и после нажатия на эту ссылку содержимое экрана должно измениться на сообщение «Привет, тест!». Отличная работа, теперь в нашем приложении есть два маршрута. Теперь давайте проверим результаты функции статического экспорта, о которой мы говорили. Вернувшись в окно терминала, запустите «npm run build». Эта команда запустит команду «следующая сборка», которая создаст готовую производственную сборку для нашей работы и сохранит результат в каталоге, вызываемом в корне нашего проекта. Если мы проверим каталог out, мы увидим что-то вроде этого:
Отличная работа, ребята. Теперь давайте переключимся и загрузим наш код в Google Cloud, чтобы мы могли увидеть сайт вживую.
Теперь, когда у нас есть готовый код, нам нужно загрузить его в Google Cloud Storage, чтобы Google Cloud мог обслуживать наш сайт в Интернете. Вернемся на вкладку Google Cloud.
Откройте гамбургер-меню в левой части экрана и выберите «Облачное хранилище». В верхней части экрана вы должны увидеть кнопку «СОЗДАТЬ». Мы нажмем на него, и начнется рабочий процесс создания. Поскольку мы пока не будем использовать собственный домен, назовите корзину как хотите, но помните об ограничении уникальности. Лично я буду использовать «somerandombucket123». Далее мы будем использовать опцию нескольких регионов в США (именно там я пишу этот пост), но вы можете свободно адаптировать ее под свой вариант использования. Затем мы выберем стандартный вариант класса по умолчанию, который должен быть предварительно заполнен для вас. Следующий вариант связан с тем, хотим ли мы, чтобы наше ведро было общедоступным через Интернет. В этом случае, поскольку мы хотим предоставить эти файлы нашим зрителям, нам нужно снять флажок «Применить запрет публичного доступа к этому сегменту», чтобы все файлы были доступны через Интернет. Мы выберем «Единый» контроль доступа, а не предложения «Защита данных», чтобы снизить затраты. Затем мы нажмем кнопку «Создать».
Теперь, когда мы создали корзину, нам нужно добавить новое разрешение, чтобы пользователи могли просматривать файлы нашей корзины. Выберите вкладку «Разрешения» и нажмите кнопку «Предоставить доступ». В поле «Новые участники» введите «allUsers» и выберите роль в разделе «Облачное хранилище» для «Просмотр объектов среды и хранилища».
Откроется диалоговое окно с вопросом, хотим ли мы сделать нашу корзину общедоступной, что мы и делаем, поэтому выберите «Разрешить публичный доступ». Затем выберите «Разрешить публичный доступ». Теперь файлы этого бакета будут общедоступны. Вернитесь на страницу обзора, щелкнув стрелку назад на странице сведений о сегменте. Вы должны увидеть вновь созданную корзину с параметрами конфигурации, которые мы использовали. Далее нам нужно будет указать сегмент нашего веб-сайта, и мы можем сделать это, щелкнув три точки в строке вновь созданного сегмента. Выберите «Изменить конфигурацию веб-сайта», и вы должны увидеть что-то вроде этого:
Для ввода индексной страницы введите «index.html», а для ввода страницы ошибок введите «404.html». Вы заметите, что эти файлы соответствуют выходным данным сборки нашего приложения Next.js, которое нам нужно и которое мы вскоре будем использовать. Завершите изменение, нажав «Сохранить».
Теперь нам нужно загрузить файлы, содержащиеся в каталоге out нашего кода, в это ведро, чтобы наш сайт мог работать! Мы можем сделать это вручную, перейдя на страницу сведений о сегменте для нашего сегмента и выбрав каждый файл или папку по отдельности. Но давайте подойдем к этому программно и напишем для этого какой-нибудь код. Вернитесь в свою IDE или туда, где вы обновляете свой код, и давайте создадим новый файл с именем upload.sh в корне нашего проекта. Добавьте следующее содержимое:
#!/bin/bash # ADD YOUR BUCKETNAME HERE (no quotes necessary) # For example: # BUCKETNAME=somerandombucket123 BUCKETNAME=somerandombucket123 echo "Removing out folder..." sleep 1; rm -rf out echo "Creating production build..." sleep 1; npm run build echo "Uploading assets to the cloud..." sleep 1; gsutil cp out/404.html gs://$BUCKETNAME gsutil cp out/favicon.ico gs://$BUCKETNAME gsutil cp out/index.html gs://$BUCKETNAME gsutil cp out/index.txt gs://$BUCKETNAME gsutil cp out/test.html gs://$BUCKETNAME gsutil cp out/test.txt gs://$BUCKETNAME gsutil cp -r out/_next gs://$BUCKETNAME
Обязательно замените «somerandombucket123» на имя вашего сегмента. Не беспокойтесь здесь слишком сильно о семантике кода. По сути, мы делаем следующее:
Прежде чем мы сможем запустить этот скрипт, нам необходимо загрузить Google Cloud CLI. Вы можете следовать инструкциям здесь . После установки вам нужно будет запустить: gcloud auth login в своем терминале. Это разрешит нам доступ к использованию Google Cloud CLI. Дополнительные инструкции и информацию по этому поводу можно найти в их документации . После успешной авторизации давайте добавим новый скрипт запуска в наш package.json. Добавьте новую запись сценария в объект «scripts», чтобы зарегистрировать наш сценарий загрузки:
"upload": "sh upload.sh"
Далее давайте проверим это. Снова откройте терминал и запустите: «npm run upload». При этом наш скрипт выполнится, и вы должны увидеть некоторые данные о загрузках, происходящих в вашу корзину. Если мы вернемся на страницу Google Cloud Storage и откроем корзину, вы увидите файлы, которые мы только что загрузили. Если вы перейдете по адресу: https://storage.googleapis.com/YOUR_BUCKET_NAME/index.html (где YOUR_BUCKET_NAME — это имя вашего сегмента), вы должны увидеть этот сайт. Но вы заметите, что стиль Next.js по умолчанию исчез, а ссылка на нашу тестовую страницу не работает. Есть идеи, почему?
Если вы откроете консоль браузера, вы увидите множество ошибок «ресурс не найден». Другими словами, браузер не может найти файлы, которые ему было поручено загрузить для вашего сайта. Если вы присмотритесь, то увидите, что URL-адрес ресурса не совсем правильный: в пути отсутствует имя нашего сегмента. Если бы мы использовали собственный домен и правильно настроили DNS, мы бы не столкнулись с этой проблемой. Но для целей этой статьи давайте добавим дополнительный код для исправления маршрутизации. Откройте src/app/page.tsx (или page.jsx) и обновите файл, чтобы он выглядел так:
import Link from "next/link"; import styles from "./page.module.css"; // Replace below with your bucketname. const BUCKET_NAME = "somerandombucket123"; const isProd = process.env.NODE_ENV === "production"; export default function Home() { return ( <main className={styles.main}> <div className={styles.description}> <p>Hello world!</p> <Link href={isProd ? '/BUCKET_NAME/test.html' : "/test"}> Test Page! </Link> </div> </main> ); }
Обязательно замените «somerandombucket123» на имя вашего сегмента. Затем обновите файл next.config, чтобы он выглядел так:
// Replace below with your bucketname. const BUCKET_NAME = "somerandombucket123"; const isProd = process.env.NODE_ENV === "production"; /** @type {import('next').NextConfig} */ const nextConfig = { assetPrefix: isProd ? 'https://storage.googleapis.com/BUCKET_NAME/' : undefined, output: "export", }; export default nextConfig;
Опять же, обязательно замените «somerandombucket123» на имя вашего корзины. В приведенном выше фрагменте кода вы заметите, что мы добавили дополнительную логику для учета имени нашего сегмента, когда переменная среды узла является рабочей (устанавливается Next.js). Мы добавляем префикс актива, чтобы исправить ошибки «ресурс не найден» в файле конфигурации и учитываем ошибку маршрутизации на нашей домашней странице, добавляя к маршруту префикс имени нашего сегмента. Давайте загрузим наш код и посмотрим, работает ли он. Еще раз начнем: npm run upload. Вернитесь на свой сайт и перезагрузите страницу. Как мы сделали? Сайт должен отражать то, что мы имеем сейчас. Если бы в начале процесса мы создали корзину, соответствующую нашему доменному имени, у нас были бы ошибки ресурсов, но все равно возникла бы проблема с маршрутизацией клиента. К сожалению, одним из недостатков этого подхода является дополнительный код, необходимый для добавления суффикса .html к маршрутам для производственного обслуживания.
Позже я расскажу о добавлении записей DNS и изменениях конфигурации, необходимых в нашу корзину для обслуживания личного домена, а также о настройке SSL для нашего веб-сайта. Надеюсь, вы узнали что-то сегодня, и в будущем я расскажу о некоторых идеях:
Спасибо за прочтение и удачи!