В предыдущем посте мы познакомились с Hyperapp, крошечной библиотекой, которую можно использовать для создания динамических одностраничных веб-приложений аналогично React или Vue.
В этом посте мы собираемся сделать вещи на ступеньку выше. Мы собираемся создать приложение локально (мы работали над CodePen ранее), узнаем, как связать его с помощью Parcel (пакетный модуль, похожий на webpack или Rollup) и развернуть его в Интернете с помощью GitHub Pages .
Не беспокойтесь, если вы не завершили проект с первого поста. Весь код предоставлен здесь (хотя я не буду подробно объяснять, что он делает), и изложенные принципы могут быть применены к большинству других проектов JavaScript.
Если вы хотите посмотреть, чем мы закончим, вы можете просмотреть готовый проект здесь или загрузить код из нашего репозитория GitHub .
Основные настройки
Чтобы продолжить, вам нужно установить Node.js и npm (они упакованы вместе). Я бы порекомендовал использовать менеджер версий, такой как nvm, для управления установкой Node ( вот как ), и если вам нужна помощь в освоении npm, ознакомьтесь с нашим удобным для начинающих руководством по npm .
Мы будем использовать команды терминала для создания файлов и папок, но не стесняйтесь делать это, просто указав и щелкнув вместо этого, если это ваша вещь.
Для начала создайте новую папку с именем hyperlist
:
mkdir hyperlist
Теперь перейдите в этот каталог и инициализируйте новый проект, используя npm:
cd hyperlist/ npm init
Это побудит вас ответить на несколько вопросов о приложении. Это нормально, просто нажмите Enter, чтобы принять значение по умолчанию для любого из них, но вы можете добавить свое имя как автора и добавить описание приложения.
Это должно создать файл с именем package.json
внутри каталога hyperlist
который выглядит примерно так:
{ "name": "hyperlist", "version": "1.0.0", "description": "A To-do List made with Hyperapp", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "DAZ", "license": "MIT" }
Теперь нам нужно установить библиотеку Hyperapp. Это делается с помощью npm вместе с флагом --save
, что означает, что файл package.json
будет обновлен, чтобы включить его в качестве зависимости:
npm install --save hyperapp
Это может дать некоторые предупреждения об отсутствии поля репозитория. Не беспокойтесь об этом, так как мы исправим это позже. Он должен обновить файл package.json
включив в него следующую запись (может быть небольшая разница в номере версии):
"dependencies": { "hyperapp": "^1.2.5" }
Он также создаст каталог с именем node_modules
котором node_modules
все файлы Hyperapp, а также файл с именем package-lock.json
. Это используется для отслеживания дерева зависимостей для всех пакетов, которые были установлены с использованием npm.
Теперь мы готовы начать создавать приложение!
Структура папок
Общепринято помещать весь ваш исходный код в папку с именем src
. В этой папке мы собираемся поместить все наши файлы JavaScript в каталог с именем js
. Давайте создадим оба из них сейчас:
mkdir -p src/js
В предыдущем посте мы узнали, что приложения создаются в Hyperapp с использованием трех основных частей: состояния, действий и представления. В интересах организации кода мы собираемся поместить код для каждой части в отдельный файл, поэтому нам нужно создать эти файлы в каталоге js
:
cd src/js touch state.js actions.js view.js
Не беспокойся, что все они пусты. Мы скоро добавим код!
И наконец, мы вернемся в каталог src
и создадим файлы «точки входа». Это файлы, которые будут ссылаться на все остальные. Первый — index.html
, который будет содержать некоторый базовый HTML, а другой — index.js
, который будет ссылаться на все наши другие файлы JavaScript, а также на наши файлы SCSS:
cd .. touch index.html index.js
Теперь, когда наша структура папок создана, мы можем начать добавлять код и соединять все файлы вместе. Вперед!
Немного базового HTML
Начнем с добавления некоторого базового HTML-кода в файл index.html
. Hyperapp заботится о создании HTML и может отображать его непосредственно в <body>
. Это означает, что нам нужно только установить метаинформацию, содержащуюся в <head>
. За исключением значения тега <title>
, вы можете использовать один и тот же файл index.html
для каждого проекта. Откройте index.html
в вашем любимом текстовом редакторе и добавьте следующий код:
<!doctype html> <html lang='en'> <head> <meta charset='utf-8'> <meta name='viewport' content='width=device-width, initial-scale=1'> <title>HyperList</title> </head> <body> <script src='index.js'></script> </body> </html>
Теперь пришло время добавить код JavaScript!
ES6 Модули
Собственные модули JavaScript были введены в ES6 (он же ES2015). К сожалению, браузеры не спешат перенимать использование модулей ES6 изначально, хотя сейчас все начинает улучшаться . К счастью, мы все еще можем использовать их для организации нашего кода, и Parcel разберется во всех их частях.
Начнем с добавления кода для начального состояния в файл state.js
:
const state = { items: [], input: '', placeholder: 'Make a list..' }; export default state;
Это то же самое, что и объект, который мы использовали в предыдущей статье , но с объявлением export
в конце. Это сделает объект доступным для любого другого файла, который его импортирует. Делая это экспортом по умолчанию, нам не нужно явно указывать его имя, когда мы импортируем его позже.
Далее мы добавим действия в actions.js
:
const actions = { add: () => state => ({ input: '', items: state.items.concat({ value: state.input, completed: false, id: Date.now() }) }), input: ({ value }) => ({ input: value }), toggle: id => state => ({ items: state.items.map(item => ( id === item.id ? Object.assign({}, item, { completed: !item.completed }) : item )) }), destroy: id => state => ({ items: state.items.filter(item => item.id !== id) }), clearAllCompleted: ({ items }) => ({ items: items.filter(item => !item.completed) }) }; export default actions;
Опять же, это то же самое, что и объект, который мы использовали в предыдущей статье, с добавлением объявления export
в конце.
И наконец, мы добавим код представления в view.js
:
import { h } from 'hyperapp' const AddItem = ({ add, input, value, placeholder }) => ( <div class='flex'> <input type="text" onkeyup={e => (e.keyCode === 13 ? add() : null)} oninput={e => input({ value: e.target.value })} value={value} placeholder={placeholder} /> <button onclick={add}>+</button> </div> ); const ListItem = ({ value, id, completed, toggle, destroy }) => ( <li class={completed && "completed"} id={id} key={id} onclick={e => toggle(id)}> {value} <button onclick={ () => destroy(id) }>x</button> </li> ); const view = (state, actions) => ( <div> <h1><strong>Hyper</strong>List</h1> <AddItem add={actions.add} input={actions.input} value={state.input} placeholder={state.placeholder} /> <ul id='list'> {state.items.map(item => ( <ListItem id={item.id} value={item.value} completed={item.completed} toggle={actions.toggle} destroy={actions.destroy} /> ))} </ul> <button onclick={() => actions.clearAllCompleted({ items: state.items }) }> Clear completed items </button> </div>s ); export default view;
Прежде всего, этот файл использует объявление import
для импорта модуля h
из библиотеки Hyperapp, которую мы установили ранее с помощью npm. Это функция, которую Hyperapp использует для создания узлов Virtual DOM, которые составляют представление.
Этот файл содержит два компонента: AddItem
и ListItem
. Это просто функции, которые возвращают код JSX и используются для абстрагирования различных частей представления в отдельные строительные блоки. Если вы обнаружите, что используете большое количество компонентов, возможно, стоит переместить их в отдельный файл components.js
а затем импортировать их в файл view.js
Обратите внимание, что в конце файла экспортируется только функция view
. Это означает, что только эта функция может быть импортирована другими файлами, а не отдельными компонентами.
Теперь мы добавили весь наш код JavaScript, нам просто нужно собрать его все вместе в файле index.js
. Это делается с помощью директивы import
. Добавьте следующий код в index.js
:
import { app } from 'hyperapp' import state from './js/state.js' import actions from './js/actions.js' import view from './js/view.js' const main = app(state, actions, view, document.body);
Это импортирует функцию app
из библиотеки Hyperapp, а затем импортирует три файла JavaScript, которые мы только что создали. Объект или функция, которые были экспортированы из каждого из этих файлов, присваиваются переменным state
, actions
и view
соответственно, поэтому на них можно ссылаться в этом файле.
Последняя строка кода вызывает функцию app
, которая запускает приложение. Он использует каждую из переменных, созданных из наших импортированных файлов, в качестве первых трех аргументов. Последний аргумент — это HTML-элемент, в котором будет отображаться приложение — по соглашению, это document.body
.
Добавить стиль
Прежде чем приступить к созданию нашего приложения, мы должны придать ему стиль. Давайте перейдем в каталог src
и создадим папку для нашего SCSS:
mkdir src/scss
Теперь мы создадим два файла, которые будут содержать код SCSS, который мы использовали в первой части:
cd src/scss touch index.scss _settings.scss
Мы используем файл с именем _settings.scss
для хранения всех переменных Sass для различных шрифтов и цветов, которые будет использовать наше приложение. Это облегчает их поиск, если вы решите обновить любое из этих значений в будущем. Откройте файл _settings.scss
и добавьте следующий код:
// fonts @import url("https://fonts.googleapis.com/css?family=Racing+Sans+One"); $base-fonts: Helvetica Neue, sans-serif; $heading-font: Racing Sans One, sans-serif; // colors $primary-color: #00caff; $secondary-color: hotpink; $bg-color: #222;
Специфичный для приложения CSS находится в index.scss
, но нам нужно убедиться, что мы импортируем файл _settings.scss
в начале, так как переменные, которые в нем содержатся, упоминаются позже в файле. Откройте index.scss
и добавьте следующий код:
@import 'settings'; * { margin: 0; padding: 0; box-sizing: border-box; } body { padding-top: 50px; background: $bg-color; color: $primary-color; display: flex; height: 100vh; justify-content: center; font-family: $base-fonts; } h1 { color: $secondary-color; & strong{ color: $primary-color; } font-family: $heading-font; font-weight: 100; font-size: 4.2em; text-align: center; } a{ color: $primary-color; } .flex{ display: flex; align-items: top; margin: 20px 0; input { border: 1px solid $primary-color; background-color: $primary-color; font-size: 1.5em; font-weight: 200; width: 50vw; height: 62px; padding: 15px 20px; margin: 0; outline: 0; &::-webkit-input-placeholder { color: $bg-color; } &::-moz-placeholder { color: $bg-color; } &::-ms-input-placeholder { color: $bg-color; } &:hover, &:focus, &:active { background: $primary-color; } } button { height: 62px; font-size: 1.8em; padding: 5px 15px; margin: 0 3px; } } ul#list { display: flex; flex-direction: column; padding: 0; margin: 1.2em; width: 50vw; li { font-size: 1.8em; vertical-align: bottom; &.completed{ color: $secondary-color; text-decoration: line-through; button{ color: $primary-color; } } button { background: none; border: none; color: $secondary-color; outline: none; font-size: 0.8em; font-weight: 50; padding-top: 0.3em; margin-left: 5px; } } } button { background: $bg-color; border-radius: 0px; border: 1px solid $primary-color; color: $primary-color; font-weight: 100; outline: none; padding: 5px; margin: 0; &:hover, &:disabled { background: $primary-color; color: #111; } &:active { outline: 2px solid $primary-color; } &:focus { border: 1px solid $primary-color; } }
Если ваш SCSS начинает усложняться, вы можете разбить его на отдельные файлы и затем импортировать их все в index.scss
.
Теперь нам нужно связать эти файлы с нашим приложением. На самом деле мы не размещаем ссылку в нашем HTML-файле, как вы это обычно делаете с CSS. Вместо этого мы index.js
его в файл index.js
. Это потому, что мы используем SCSS, и его нужно предварительно обработать в CSS. Parcel сделает это за нас, а также разберется, связывая HTML-файл со стандартным CSS-файлом, который он создает.
Чтобы импортировать файлы SCSS, нам просто нужно обновить наш файл index.js
в него следующую строку:
import './scss/index.scss'
Теперь, когда весь наш код завершен, пришло время начать работу над процессом сборки!
галдеж
Babel преобразует современный код JavaScript в код, который может использовать большинство браузеров. Он также позаботится о переписывании кода JSX в чистый JavaScript.
Чтобы использовать Babel с преобразованиями JSX, нам нужно установить его вместе с плагином JSX:
npm install --save babel-plugin-transform-react-jsx babel-preset-env
Нам также нужно создать файл .babel.rc
который будет .babel.rc
Babel использовать функцию h
из Hyperapp при обработке JSX. Следующий код создаст файл с соответствующей информацией:
echo '{ "plugins": [["transform-react-jsx", { "pragma": "h" }]] }' > .babelrc
Обратите внимание, что это скрытый файл , поэтому вы не сможете увидеть его после его создания!
Посылка
К сожалению, наш код в настоящее время не работает во всех браузерах. Нам нужно использовать процесс сборки для переноса нашего кода ES6 + в ES5 и объединения всех наших файлов JS в один файл. Давайте использовать Parcel, чтобы сделать это.
Parcel — это пакет модулей, похожий на webpack или Rollup, который обещает нулевую конфигурацию и невероятно быстр. Это позволяет нам писать современный JavaScript в отдельных файлах, а затем объединять их в один минимизированный файл JavaScript, который сможет использовать большинство браузеров. Он также поддерживает несколько файлов CSS, SCSS и PostCSS из коробки.
Прежде всего, давайте установим Parcel:
npm install --save parcel-bundler
Посылка поставляется с собственным встроенным сервером. Это означает, что вы можете продолжать разрабатывать и вносить изменения в приложение, а Parcel создаст его в фоновом режиме, поэтому любые изменения будут отображаться мгновенно!
Чтобы запустить сервер, введите следующую команду:
./node_modules/.bin/parcel src/index.html --out-dir docs
Это указывает, что точкой входа является файл index.html
. Это все, что нужно знать Parcel, поскольку он перейдет по ссылке на index.js
которая находится в этом файле, а затем будет следовать директивам import
в этом файле.
Он также указывает, что папка с именем docs
будет использоваться для вывода всех статических файлов в. По умолчанию это обычно называется dist
— но, как вы увидите позже, нам нужно, чтобы он назывался docs
чтобы мы могли интегрировать его с GitHub Pages.
Вы также должны увидеть сообщение о том, что приложение создается в окне терминала. Вы можете даже заметить, что Parcel устанавливает для вас модуль npm node-sass
, поскольку он автоматически замечает, что мы используем файлы SCSS, но также и что у нас не установлен node-sass
. Как это круто?!
Через несколько секунд вы должны увидеть сообщение, подобное следующему:
Server running at http://localhost:1234 Built in 3.15s.
Сервер теперь запущен, и если вы откроете браузер и перейдете по адресу http: // localhost: 1234 , вы увидите, что приложение запущено. Это будет обновляться на лету, поэтому любые изменения, внесенные вами в код, будут отражены на странице сразу (или после небольшой паузы для перестройки кода). Он также загружает модули, поэтому он автоматически установит все модули npm, которые требуются, когда они необходимы, как это было сделано с «node-sass». Потрясающие!
Как только вы будете довольны тем, как выглядит сайт, самое время создать статический сайт. Прежде всего, остановите работу сервера, удерживая Ctrl и c вместе. Затем выполните в терминале следующую команду:
./node_modules/.bin/parcel build src/index.html --out-dir docs --public-url ./
Это создаст статические файлы и поместит их в папку с docs
.
Если вы берете пик в папке с docs
, вы должны найти файл с именем index.html
. Откройте его в браузере, и вы увидите, что сайт работает, используя только статические файлы в папке docs
. Parcel объединил весь соответствующий код и использовал Babel для переноса нашего современного JavaScript в один файл JavaScript и использовал node-sass для предварительной обработки наших файлов SCSS в один файл CSS. Откройте их, и вы увидите, что код также был свернут!
Сценарии npm
В npm есть полезная функция, называемая скриптами, которая позволяет вам запускать определенные фрагменты кода с помощью одной команды. Мы можем использовать это для создания пары скриптов, которые ускорят использование Parcel.
Добавьте следующее в раздел «scripts» файла package.json
:
"start": "parcel src/index.html --out-dir docs", "build": "parcel build src/index.html --out-dir docs --public-url ./"
Теперь мы можем просто запустить следующие команды для запуска сервера:
npm start
И следующая команда запустит процесс сборки:
npm run build
Если вы никогда не использовали сценарии npm или хотели бы пройти переподготовку, возможно, вы захотите ознакомиться с нашим удобным для начинающих руководством по этой теме .
Развертывание на страницах GitHub
GitHub — это отличное место для размещения вашего кода, а также отличная функция GitHub Pages, которая позволяет размещать статические сайты на GitHub. Для начала вам нужно убедиться, что у вас есть учетная запись GitHub и у вас установлен git на локальном компьютере.
Чтобы убедиться, что мы не gitignore
ненужные файлы, давайте добавим файл hyperlist
каталог hyperlist
:
touch .gitignore
Как следует из названия, этот файл сообщает git, какие файлы (или шаблоны) он должен игнорировать. Обычно он используется, чтобы избежать фиксации файлов, которые бесполезны для других соавторов (например, создание временных файлов IDE и т. Д.).
Я бы рекомендовал добавить следующие элементы, чтобы убедиться, что они не отслеживаются git (помните, что gitignore
— это скрытый файл!):
# Logs logs *.log npm-debug.log* # Runtime data pids *.pid *.seed # Dependency directory node_modules # Optional npm cache directory .npm # Optional REPL history .node_repl_history # Cache for Parcel .cache # Apple stuff .DS_Store
Теперь мы готовы инициализировать git в каталоге hyperlist
:
git init
Далее мы добавляем все файлы, которые мы создали до сих пор:
git add .
Затем мы передаем эти файлы для контроля версий:
git commit -m 'Initial Commit'
Теперь, когда наши важные файлы отслеживаются с помощью git, нам нужно создать удаленный репозиторий на GitHub. Просто войдите в свою учетную запись, нажмите кнопку « Новый репозиторий» и следуйте инструкциям. Если вы застряли, вы можете обратиться к документации GitHub здесь: Создать Репо .
После того, как вы это сделаете, вам нужно добавить URL вашего удаленного репозитория GitHub на вашем локальном компьютере:
git remote add origin https://github.com/<username>/<repo-name>.git
Обязательно замените <username>
и <repo-name>
на правильные значения. Если вы хотите убедиться, что вы все сделали правильно, вы можете использовать git remote -v
.
И, наконец, нам нужно отправить наш код на GitHub:
git push origin master
Это подтолкнет весь ваш код в ваш репозиторий GitHub, включая статические файлы в каталоге docs
. GitHub Pages теперь можно настроить для использования файлов в этом каталоге. Для этого войдите в хранилище на GitHub, перейдите в раздел « Настройки » хранилища и прокрутите вниз до раздела « Страницы GitHub ». Затем в разделе « Источник» выберите параметр «Папка master branch / docs», как показано на снимке экрана ниже:
Это должно означать, что теперь вы можете получить доступ к приложению по следующему адресу: https://username.github.io/repo-name.
Например, вы можете посмотреть наши по адресу sitepoint-editors.github.io/hyperlist/ .
Workflow
Отныне, если вы вносите какие-либо изменения в свое приложение, вы можете придерживаться следующего рабочего процесса:
- запустить сервер разработки:
npm start
- внести любые изменения
- проверьте, что изменения работают на сервере разработки
- выключите сервер, удерживая Ctrl + c
- перестройте приложение:
npm run build
- внесите изменения для коммита:
git add .
- зафиксировать все изменения в git:
git commit -m 'latest update'
- нажмите изменения в GitHub:
git push origin master
.
Мы можем ускорить этот процесс, создав сценарий npm, чтобы выполнить последние три шага за один раз. Добавьте следующее к записи «scripts» в package.json
:
"deploy": "npm run build && git add . && git commit -a -m 'latest build' && git push origin master"
Теперь все, что вам нужно сделать, если вы хотите развернуть свой код после внесения каких-либо изменений, это выполнить следующую команду:
npm run deploy
Вот и все, ребята!
И это подводит нас к концу этого урока. Я использовал приложение, которое мы создали в первой части этого руководства, но принципы остаются неизменными для большинства проектов JavaScript. Надеюсь, я продемонстрировал, как легко использовать Parcel для создания статического сайта JS и автоматического развертывания его на страницах GitHub с помощью одной команды!