Иногда вам не нужен такой фреймворк, как Vue или React, чтобы продемонстрировать идею или концепцию в JavaScript. Вам просто нужна независимая от фреймворка, простая среда разработки JavaScript, чтобы поэкспериментировать с такими вещами, как, например, сервисные работники, веб-работники, новый синтаксис JavaScript или IndexedDB. В этом сообщении блога вы узнаете, как быстро создавать прототипы простых приложений JavaScript с использованием ParcelJS для создания такой среды с нулевой конфигурацией и минимальными затратами на разработку.

Посетите Блог Auth0 🔐 и найдите все, что вам нужно знать об инфраструктуре идентификации, управлении доступом, системе единого входа, аутентификации JWT и последних новостях в области безопасности. 👉 AUTH0 БЛОГ👈

ParcelJS — это признанный сборщик веб-приложений, который позволяет платформам облачной разработки, таким как CodeSandbox, создавать простые проекты JavaScript. Его разработчики позиционируют его как быстрый сборщик с нулевой конфигурацией со следующими функциями:

  • Быстрое время связки.
  • Нулевое разделение кода конфигурации.
  • Горячая замена модуля без настройки.
  • Автоматические преобразования с использованием Babel, PostCSS и PostHTML при необходимости.
  • Parcel имеет встроенную поддержку JS, CSS, HTML, файловых ресурсов и многого другого без каких-либо плагинов или загрузчиков.
  • Читаемый журнал ошибок путем печати кадров кода, выделенных синтаксисом, при обнаружении ошибок.

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

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

ОТПРАВИТЬ ЭТО В Твиттер

Вы можете найти отточенную версию этого упражнения в parcel-prototype репозитории на GitHub. Тем не менее, я призываю вас следить за постом и постепенно создавать прототип приложения ParcelJS, чтобы лучше понять тяжелую работу, которую ParcelJS делает для вас, и некоторые особенности его системы замены горячего модуля.

Настройка нулевой конфигурации ParcelJS

Точкой входа для ParcelJS может быть файл любого типа. Однако рекомендуется использовать файл JavaScript или HTML, поскольку ParcelJS будет следовать зависимостям, объявленным в файле, для создания всего приложения. Этот входной файл будет частью проекта NPM; таким образом, вам необходимо установить npm.

Выполните следующие действия, чтобы установить NPM, если необходимо.

Для начала перейдите к своему терминалу и сделайте каталог, в котором вы хотите сохранить этот учебный проект, своим текущим рабочим каталогом. После этого создайте папку с именем parceljs-prototype и сделайте ее своим текущим рабочим каталогом. Вы можете легко сделать это с помощью следующей команды:

mkdir parceljs-prototype && cd parceljs-prototype

Эта однострочная команда создает каталог parceljs-prototype, а затем делает его текущим рабочим каталогом.

Затем инициализируйте проект NPM и установите parcel-bundler локально:

npm init -y npm install parcel-bundler --save-dev

После завершения установки откройте проект в предпочитаемой вами среде IDE или редакторе кода.

Вы можете запустить code . или webstorm ., чтобы открыть текущий рабочий каталог, если вы установили инструменты командной строки для Visual Studio Code или WebStorm.

Для запуска вашего проекта вы будете использовать сценарии NPM. Обновите package.json, чтобы включить сценарии dev и build:

{ "name": "parceljs-prototype", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "parcel <your entry file>", "build": "parcel build <your entry file>" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "parcel-bundler": "^1.10.3" } }

Теперь вам нужно создать точку входа для приложения. Разработчик должен выбрать тип файла, который будет использоваться в качестве точки входа. В этом руководстве вы будете использовать файлы index.html и index.js, которые будут находиться в каталоге src. Создайте следующую файловую структуру для проекта:

parceljs-prototype |- package.json |- /src |- index.html |- index.js

Вы можете быстро создать эти файлы, введя следующие команды:

macOS/Linux:

mkdir src && touch src/index.html src/index.js

Windows:

mkdir src && echo.> src/index.html && echo.> src/index.js

mkdir — это кроссплатформенная команда для создания каталогов. Однако touch доступен только в Unix и Unix-подобных операционных системах. echo — это эквивалент touch для Windows. echo. создает файл с одной пустой строкой.

Дайте жизнь обоим файлам со следующим содержимым:

// src/index.js const createElement = (message) => { const element = document.createElement("div"); element.innerHTML = message; return element; }; document.body.appendChild(createElement("ParcelJS ready to ship!"));
<!-- index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ParcelJS Prototype</title> </head> <body> <script src="./index.js"></script> </body> </html>

В src/index.html внутри тега <body> вы загружаете файл index.js через тег <script>.

<script src="./index.js"></script>

Когда вы связываете свой основной файл JavaScript с вашим основным файлом HTML, используя относительный путь, ParcelJS обработает файл JavaScript для вас и заменит его ссылку в index.html URL-адресом выходного файла.

У вас есть то, что вам нужно, чтобы раскрутить это приложение! ParcelJS поставляется со встроенным сервером разработки — нет необходимости устанавливать какие-либо дополнительные зависимости. Этот сервер разработки автоматически перестраивает ваше приложение, когда вы вносите изменения в исходные файлы. Чтобы улучшить ваш опыт и эффективность разработки, сервер разработки ParcelJS поставляется с горячей заменой модуля из коробки.

Чтобы запустить приложение, вам нужно указать parcel на ваши входные файлы. Вернитесь к package.json и замените заполнитель в NPM-скриптах ParcelJS своим именем файла записи, в данном случае src/index.html:

{ "name": "parceljs-prototype", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "parcel src/index.html", "build": "parcel build src/index.html" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "parcel-bundler": "^1.10.3" } }

В командной строке выполните скрипт dev NPM:

npm run dev

Через несколько миллисекунд вы увидите следующее сообщение в командной строке:

Server running at http://localhost:1234 ✨ Built in 731ms.

Укажите в браузере этот адрес или щелкните следующую ссылку, чтобы открыть его: http://localhost:1234.

Теперь вы увидите сообщение ParcelJS ready to ship!, напечатанное на экране браузера:

Что ж, это было легко! Все, что осталось, — это добавить больше модулей JavaScript, таблиц стилей и изображений, чтобы сделать это приложение более совершенным.

Импорт модулей с помощью ParcelJS с нулевой конфигурацией

Создайте еще один модуль, который добавляет еще один элемент в DOM. Под src создайте banner.js:

макОС/Линукс:

touch src/banner.js

Окна:

echo.> src/banner.js

Откройте этот файл и заполните его следующим образом:

// src/banner.js const createBanner = () => { const link = document.createElement("a"); link.innerHTML = "Learn ParcelJS by Devon Govett."; link.href = "https://parceljs.org/"; link.target = "_blank"; return link; }; export default createBanner;

Сохраните изменения, внесенные в src/banner.js.

Затем обновите src/index.js следующим образом и сохраните файл:

// src/index.js import createBanner from "./banner.js"; const createElement = message => { const element = document.createElement("div"); element.innerHTML = message; return element; }; document.body.appendChild(createElement("ParcelJS ready to ship!")); document.body.appendChild(createBanner());

Теперь браузер показывает сообщение с гиперссылкой внизу:

Однако есть проблема, связанная с системой HMR. В конце src/index.js просто нажмите клавишу <ENTER>, чтобы создать новую строку и сохранить файл. Сделайте это несколько раз. Теперь взгляните на браузер... Вы увидите, что сообщение и гиперссылка копируются снова и снова при каждом сохранении!

Что происходит? GitHub Issue #289 on the parcel-bundler repo содержит несколько ответов. Основной файл JavaScript, src/index.js, создает элементы DOM с помощью JavaScript и добавляет их в DOM с помощью метода document.body.appendChild(). Однако всякий раз, когда src/index.js обновляется, логика манипулирования DOM запускается повторно, и вкладка браузера, на которой загружено приложение, в конечном итоге будет иметь дублирующиеся элементы DOM.

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

Замена горячего модуля ParcelJS

Из Документации ParcelJS по горячей замене модулей мы можем узнать следующие ключевые понятия:

  • HMR автоматически обновляет модули в браузере во время выполнения без необходимости обновления всей страницы.
  • Состояние приложения может сохраняться при небольших изменениях.
  • HMR поддерживает файлы JS и CSS.
  • В производственном режиме HMR автоматически отключается.

Как работает ГМР?

  • ParcelJS перестраивает то, что изменилось.
  • Он отправляет обновление всем клиентам, на которых выполняется код.
  • Новый код заменяет старый код и переоценивается вместе со всеми родителями.

ParcelJS предлагает module.hot API для подключения к процессу HMR. С помощью этого API вы можете уведомить свой код, когда модуль будет удален или когда появится новая версия. Из этого API выделяются два метода: module.hot.accept и module.hot.dispose.

Документы ParcelJS объясняют, что…

module.hot.accept вызывается с помощью функции обратного вызова, которая выполняется при обновлении этого модуля или любой из его зависимостей.

module.hot.dispose принимает обратный вызов, который вызывается, когда этот модуль собирается заменить.

if (module.hot) { module.hot.dispose(function() { // module is about to be replaced }) module.hot.accept(function() { // module or one of its dependencies was just updated }) }

При работе с WebGL и Canvas API или при создании элементов DOM с помощью JavaScript некоторые пользователи замечали проблемы с производительностью, поскольку код многократно перезапускался и происходило дублирование DOM. В GitHub Issue #289 автор объяснил следующее:

🤔 Ожидаемое поведение Я хотел бы разрабатывать так же, как файл JS запускается/загружается в браузере (т.е. один раз, а не много раз). Если возможно, я хотел бы заменить JavaScript HMR простой функциональностью window.location.reload(). Однако другие функции (например, CSS) должны по-прежнему использовать HMR/inject без жесткой перезагрузки.

😯 Текущее поведение В настоящее время приведенный выше код при сохранении несколько раз создаст в теле несколько элементов canvas.

💁 Возможное решение Способ включения/выключения регулярной горячей перезагрузки. Я предполагаю, что это может уже существовать, но я не смог его найти, так что, возможно, это больше проблема документации?

В ходе обсуждения автор номера также поясняет, что:

Сейчас любое изменение модуля в вашем приложении вызовет перезагрузку корневого уровня, а это означает, что в настоящее время нет четкого способа избежать таких проблем, как дублирование прослушивателей оконных событий, одновременные циклы requestAnimationFrame и т. д.

Девон Говетт, автор ParcelJS, предложил автору задачи следующее решение:

Вы можете сделать что-то подобное, если не хотите, чтобы модуль выполнялся повторно:

if (module.hot) { module.hot.dispose(function () { window.location.reload(); }); }

Это вызовет перезагрузку при удалении модуля, а не после повторного выполнения модуля.

Вы также можете использовать этот хук, чтобы сохранить свое состояние на потом и восстановить его при принятии. HMR требует некоторой работы, чтобы сделать все правильно, поэтому существуют такие вещи, как react-hot-loader. Parcel в значительной степени не зависит от этого: он дает вам подсказки, когда модуль изменяется, и вы сами решаете, что с этим делать.

Сейчас любое изменение модуля в вашем приложении вызовет перезагрузку на корневом уровне

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

Джаспер Де Мур, еще один участник ParcelJS, объясняет в GitHub Issue #344 следующее в отношении дублирования DOM:

Насколько мне известно, это, вероятно, просто неправильная обработка HMR, вы можете написать функцию dispose для удаления объекта из DOM или функцию accept для его обновления.

Если вы хотите использовать какой-либо фреймворк, он уже встроен, но если вы используете чистый js, это не так

Эта проблема создает дополнительную сложность, но также помогает разработчикам лучше понять, как работает HMR. Добавление фрагмента кода, предложенного Девоном, к src/index.js решает проблему. Обновите код следующим образом:

// src/index.js import createBanner from "./banner.js"; const createElement = message => { const element = document.createElement("div"); element.innerHTML = message; return element; }; document.body.appendChild(createElement("ParcelJS ready to ship!")); document.body.appendChild(createBanner()); if (module.hot) { module.hot.dispose(function() { window.location.reload(); }); }

Сохраните файл и перезагрузите браузер.

Нажимая клавишу <ENTER> для создания новой строки и сохранения файла каждый раз, вы увидите немного дополнительного мигающего содержимого, но после этого на экране браузера отображается содержимое без дубликатов. Размещение кода Devon на верхнем уровне, входной файл JavaScript поможет смягчить эту проблему. Это небольшая цена за дополнительное удобство и скорость, которые предлагает ParcelJS при настройке ванильных приложений JavaScript.

«Узнайте, как работает замена горячего модуля ParcelJS для ванильных проектов JavaScript.»

ОТПРАВИТЬ ЭТО В Твиттер

Импорт модулей NPM с помощью ParcelJS

Тот же принцип, который вы видели при импорте локального модуля, можно применить к любым модулям, установленным в вашем проекте через npm. Например, если вы хотите использовать lodash, просто выполните npm install --save lodash и import в любом файле, который в этом нуждается:

npm install --save lodash

Обновите src/banner.js следующим образом:

// src/banner.js import _ from "lodash"; const createBanner = () => { const link = document.createElement("a"); link.innerHTML = _.join(["Learn", "ParcelJS", "Today"], " "); link.href = "https://parceljs.org/"; link.target = "_blank"; return link; }; export default createBanner;

При импорте локальных модулей вы используете ./relative-path-to-module в качестве пути к модулю. При импорте модулей NPM вы используете npm-module-name в качестве пути к модулю.

Сохраните изменения на src/banner.js и посмотрите по гиперссылке в самом браузере обновление, чтобы выглядеть очень ретро 90-х: Learn ParcelJS Today.

Что насчет CSS?

Добавление таблиц стилей CSS в ParcelJS

Работает ли процесс добавления файлов CSS так же, как добавление модулей JavaScript? Посмотрим. Вы можете сделать текущую страницу красивее следующим образом:

  • Под src создайте banner.css:

макОС/Линукс:

touch src/banner.css

Окна:

echo.> src/banner.css
  • Откройте src/banner.css и заполните его следующим:
/* src/banner.css */ .banner { position: fixed; background: #1A6DB9; color: white; padding: 25px; }

Сохраните изменения, внесенные в src/banner.css.

Затем обновите src/banner.js, чтобы импортировать banner.css и добавить класс banner в элемент баннера <a>:

// src/banner.js import _ from "lodash"; import "./banner.css"; const createBanner = () => { const link = document.createElement("a"); link.innerHTML = _.join(["Learn", "ParcelJS", "Today"], " "); link.href = "https://parceljs.org/"; link.target = "_blank"; link.classList = "banner"; return link; }; export default createBanner;

Сохраните src/banner.js.

Перезапустите сервер разработки ParcelJS, остановив его и снова выполнив npm run dev, чтобы ParceJS мог связать новый файл CSS в качестве зависимости. Обновите вкладку браузера, и теперь гиперссылка должна быть оформлена.

Вот вам! С ParcelJS вы можете импортировать файлы CSS в модуль JavaScript без какой-либо дополнительной настройки или установки плагина/загрузчика.

Что делать, если вы хотите добавить несколько изображений? Вы можете попробовать это дальше.

Загрузка изображений с помощью ParcelJS

Начните с загрузки изображения логотипа ParcelJS. Сохраните его как parceljs-logo.png и переместите в каталог src.

Обновите src/index.js, чтобы импортировать изображение следующим образом:

// src/index.js import createBanner from "./banner.js"; import ParcelImg from "./parceljs-logo.png"; const createElement = message => { const element = document.createElement("div"); element.innerHTML = message; return element; }; const createImage = image => { const element = document.createElement("div"); const imageElement = new Image(); imageElement.src = image; element.appendChild(imageElement); return element; }; document.body.appendChild(createElement("ParcelJS ready to ship!")); document.body.appendChild(createBanner()); document.body.appendChild(createImage(ParcelImg)); if (module.hot) { module.hot.dispose(function() { window.location.reload(); }); }

Сохраните файл и посмотрите в браузере. Логотип ParcelJS теперь загружается на экран:

Точно так же вы могли импортировать файлы изображений в модуль JavaScript. Это произошло в очередной раз без какой-либо дополнительной настройки или установки плагина/загрузчика.

Создание приложения JavaScript с помощью ParcelJS

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

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

npm run build

После завершения сценария build ваши производственные файлы будут находиться в папке dist.

Вывод

Для быстрого создания простых прототипов JavaScript достаточно ресурсов JavaScript, CSS и изображений, чтобы многое сделать. Теперь вы знаете, как ParcelJS помогает вам создавать среду разработки для проектов JavaScript без необходимости настройки. Используйте этот надежный инструмент локально для быстрого создания красивых приложений JavaScript или, если хотите, не стесняйтесь использовать облачные среды, использующие ParcelJS, такие как CodeSandbox, онлайн-редактор кода для Интернета.

Вы можете найти отточенную версию этого упражнения в репозитории parcel-prototype на GitHub. В окончательной версии используются шрифты Google и улучшенная структура для создания гораздо более привлекательного баннера ParcelJS с использованием ParcelJS!

В стороне: аутентификация Auth0 с помощью JavaScript

В Auth0 мы широко используем полнофункциональный JavaScript, чтобы помочь нашим клиентам управлять идентификацией пользователей, включая сброс паролей, создание и инициализацию, блокировку и удаление пользователей. Мы также создали бессерверную платформу под названием Auth0 Extend, которая позволяет клиентам безопасно запускать произвольные функции JavaScript. Поэтому неудивительно, что использование нашей платформы управления идентификацией в веб-приложениях JavaScript не составляет труда.

Auth0 предлагает бесплатный уровень, чтобы начать работу с современной аутентификацией. Проверьте это или зарегистрируйте бесплатную учетную запись Auth0 здесь!

Это так же просто, как установить модули узла auth0-js и jwt-decode следующим образом:

npm install jwt-decode auth0-js --save

Затем реализуйте в своем JS-приложении следующее:

const auth0 = new auth0.WebAuth({ clientID: "YOUR-AUTH0-CLIENT-ID", // E.g., you.auth0.com domain: "YOUR-AUTH0-DOMAIN", scope: "openid email profile YOUR-ADDITIONAL-SCOPES", audience: "YOUR-API-AUDIENCES", // See https://auth0.com/docs/api-auth responseType: "token id_token", redirectUri: "http://localhost:9000" //YOUR-REDIRECT-URL }); function logout() { localStorage.removeItem('id_token'); localStorage.removeItem('access_token'); window.location.href = "/"; } function showProfileInfo(profile) { var btnLogin = document.getElementById('btn-login'); var btnLogout = document.getElementById('btn-logout'); var avatar = document.getElementById('avatar'); document.getElementById('nickname').textContent = profile.nickname; btnLogin.style.display = "none"; avatar.src = profile.picture; avatar.style.display = "block"; btnLogout.style.display = "block"; } function retrieveProfile() { var idToken = localStorage.getItem('id_token'); if (idToken) { try { const profile = jwt_decode(idToken); showProfileInfo(profile); } catch (err) { alert('There was an error getting the profile: ' + err.message); } } } auth0.parseHash(window.location.hash, (err, result) => { if (err || !result) { // Handle error return; } // You can use the ID token to get user information in the frontend. localStorage.setItem('id_token', result.idToken); // You can use this token to interact with server-side APIs. localStorage.setItem('access_token', result.accessToken); retrieveProfile(); }); function afterLoad() { // buttons var btnLogin = document.getElementById('btn-login'); var btnLogout = document.getElementById('btn-logout'); btnLogin.addEventListener('click', function() { auth0.authorize(); }); btnLogout.addEventListener('click', function() { logout(); }); retrieveProfile(); } window.addEventListener('load', afterLoad);

Получите полный пример, используя этот код.

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

Первоначально опубликовано на auth0.com.