Даниэль Дойч
Задача приложений для голосования на FreeCodeCamp был первый проект FreeCodeCamp в учебной программе, который поразил меня так же сильно. Я просто не мог сделать это так же легко, как и все остальные проблемы. Так много знаний во многих концепциях необходимо его построить.
Я не нашел никаких учебных пособий или примеров, которые сломали эту проблему с современными инструментами. Поэтому я решил документировать мой процесс создания его.
В этом руководстве будет использоваться:
- Монгодб
- выражать
- React + Redux.
- Node.js.
также известен как «Mern-Stack».
О чем эта статья
Я опишу процесс создания приложения для голосования для FreeCodecamp Challenge Отказ
Это не оптимизированный пример для создания приложения. Я открыт для обратной связи любого рода. Я все еще новичок, а также оставил некоторые вещи открытыми.
Это не разработано как учебник! Это просто документация, которую я написал при создании приложения.
Состав
Я делю эту статью на разделы заднего конца, интерфейс, визуализации данных и процесса развертывания. Проект будет доступен как код открытого исходного кода на GitHub. Именно здесь вы можете следить за коммитами и конечным результатом.
Среда разработки
- Равнина JavaScript
- Node.js.
- Экспресс (JS Framework)
- Монгодб (База данных)
- Пряжа (Управление пакетом)
- Visual Studio Код в качестве редактора
- Почтальон (Тестирование API)
- Robomongo/Robo 3T (работает быстрее с MongoDB)
Пакеты/Особенности/зависимости
Общий
- ( ES 6 (Спецификация JS Scripting-языковая))
- Eslint С расширением Airbnb (для записи более высокого качества)
- Номемон (Перезапустите сервер, когда происходят изменения)
- Бабел (JavaScript Compiler)
- WebPack (Модуль Bundler/Builder)
- Доценв (Для настройки переменных среды)
- Подробнее (генератор случайных идентификаторов)
Спина
- Node.js (Среда выполнения JS для сервера)
- Монгодб (База данных на основе документов)
- Connect-Mongo (для хранения сеансов в MongoDB)
- Тело-парсер (для анализа входящих запросов)
- Экспресс (Чтобы сделать приложение Run)
- мангуст (Моделирование данных объекта для упрощения взаимодействия с MongoDB)
- Морган (HTTP запрос Logger Middleware)
- Паспорт (Аутентификация промежуточного программного обеспечения для Node.js)
Внешний интерфейс
- Реагировать (JS Framework)
- Redux (государственное управление для реагирования)
- Redux Thunk (асинхронный redux)
- Материализация CSS (Рамки для дизайна материала)
- React Router (Маршрутизация в Frontend)
Визуализация
- Реагировать Google Charts (React Wrapper для Google Charts)
- Google Charts (для визиоализация данных)
Развертывание/DEVOPS.
- Heroku (Паа, чтобы запустить приложения в облаке)
- (Единица) Тестирование: не реализовано в этом приложении (но обычно это должно быть)
Первые вещи в первую очередь
Сначала я настрою свою среду:
- Добавить Гит Для контроля версий
- Создайте свое управление пакетом с Инитация пряжи
- Добавить Экспресс Для быстрого развития веб-разработки
- Добавьте Номемон Пакет для перезапуска вашего сервера на изменениях
- Добавить Eslint.rc для вашего Eslint конфигурация
- Добавить Бабел и соответствующие плагины для составления JS
В качестве дополнительной интеграции я буду использовать:
- Трэвис CI (для непрерывной интеграции)
- Код климата (Для качества кода)
- Утверждено (Мониторинг веб-сервисов, особенно проверка развертывания – гарантия качества)
Вот мой коммит на Github после установки.
Спина
Для меня спиной самый сложный. Так вот где начну.
Настройте пакеты, промежуточное программное обеспечение и монгуст
Я буду использовать:
- Тело-парсер Для анализа тел запроса
- Морган Для ввода HTTP-запросов
- Сжатие для сжатия органов
- Шлем Для установки базовой безопасности с заголовками HTTP
- мангуст Инструмент моделирования объектов для асинхронного соединения базы данных
Следующие шаги:
- Создать Константы Файл, чтобы установить различные переменные среды и Соответствующие настройки
- Создать Indirdwar e файл пропустить промежуточное программное обеспечение к вашему приложению и дифференцировать для среды. Использовать боговестный и Морган пакеты здесь.
- Создать база данных Файл для настройки подключения MongoDB
- Модулируйте свой код и аутсорсинг ваших констант, промежуточное программное обеспечение и соединение с базой данных. Это для сохранения небольших файлов.
- Импортируйте все в своем app.js Файл, пройти в
промежуточное программное обеспечениеФункция и проверить настройку простымhttp. запрос
Вот мой коммит на Github После этой установки.
Настройте свои маршруты
Пересмотрите истории пользователей и выложите свои маршруты соответственно.
После Круд подход :
Как неаутентифицированный пользователь, который я хочу:
- Смотрите все опросы (R)
- Смотрите отдельные опросы (R)
- Голосуйте на доступные опросы (C)
Как аутентифицированный пользователь, который я хочу к
- Смотрите и прочитайте все опросы (R)
- Смотрите отдельные опросы (R)
- Голосуйте на доступные опросы (C)
- Создать новые опросы (C)
- Создание новых вариантов и голосов (в)
- Удалить опросы (D)
Следовательно:
- настроить Обработка ошибок в виде промежуточного программного обеспечения
- Настройте свой объект маршрутизатора
- Создайте свой Get, Post, Delete маршруты и ответ с объектами JSON
- Проверьте настройки маршрутов с помощью почтальон (Все должны иметь код состояния 200)
- Подключите свои маршруты Ваше промежуточное программное обеспечение и App.js
Установите Mongoose и ваши схемы и подключите все к своим маршрутам
При настройке схем подумайте о том, как вы хотите структурировать документы, которые вы будете хранить в базе данных. В этом примере нам нужно хранить пользователь для процесса аутентификации и опроса с ответами.
Для опросов нам нужно:
- вопрос
- Ответы и голоса
Помните, что MLAB создает «коллекции системы». «Они бросают» дублируют ключевую ошибку ключевой ошибки DUP: {: NULL} «Ошибка в почтовостеке, при создании новых опросов. До сих пор я не нашел решение, но удаление всех коллекций позволяет нам начать снова.
- Используйте Доценв Пакет для хранения ваших учетных данных в окружающей среде и добавьте файл .env в .gitignore (Если вы сделаете свой проект с открытым исходным кодом)
- Подключите вас маршруты с вашей моделью Mongoose для обработки документов в MongoDB
Обязательно прочитайте Документы Если вы застряли. Эта часть довольно тяжелая, когда вы не покончили с Mongoose и MongoDB!
Вот что мои комбиниты выглядели на Github после этих шагов Отказ
Установить аутентификацию и авторизацию с Twitter
Я хочу использовать вход в Twitter, как ОАУТ провайдер для аутентификации. Это обеспечивает лучший пользовательский опыт, и я также должен исследовать ОАУТ.
OAUTH – это стандартный протокол, который позволяет пользователям авторизовать API доступа к Интернету и настольному или мобильным приложениям. После предоставленного доступа уполномоченное приложение может использовать API от имени пользователя.
Конечно, я нашел Великая статья О том, как настроить процесс аутентификации в Nodejs. После того, как я потерпел неудачу правильно реализовать его в моем приложении, и мне потребовалось целый день, я решил погрузиться прямо в Документация паспорта Действительно
Я люблю цитату, которые они ставят туда:
«Несмотря на то, что сложности, участвующие в аутентификации, код не должен быть сложен».
⭐ Опять же, как напоминание: прочитайте документацию!
- Зарегистрируйте свое приложение на Приложения Twitter и получить ваши настройки прямо. Определите уровень доступа и URL обратного вызова
- Добавить заграничный пасспорт , паспорт-твиттер и Экспресс-сессия Пакеты в ваше заявление
- Создайте файл, определяющий стратегию паспорта для Twitter
- Для поддержки входа в систему сеанса паспорт должен сериализовать и десериализировать пользователя
- Pass Passport к вашей конфигурации паспорта и подключите Passport.initialize и Passport.Session к вашему приложению как промежуточное программное обеспечение. Используйте Express-Session до этого!
- Настройте маршруты для аутентификации и обратный вызов
Проверьте мой коммит на Гадость после этих шагов.
После этого подключите процесс аутентификации к вашей базе данных
⭐ Совет: Используйте для вашего обратного вызова и тестирование всегда http://127.0.0.1:3000/ вместо http://localhost: 3000/ , так как он решает много проблем, что может произойти с помощью паспорта-Twitter. ?
- Создайте схему Mongoose для ваших пользователей, чтобы отслеживать их в вашей базе данных
- Заполните функцию обратного вызова вашего файла Passport.js при внедрении стратегии Twitter. Фильтуйте свою базу данных для пользователя и создайте новый Если пользователь не существует
- Используйте Connect-Mongo Пакет для создания Mongostore и хранить свои сеансы в MongoDB
- Создайте функцию для проверки, если пользователь аутентифицируется. Внедрить его в нужных маршрутах при предоставлении достаточной авторизации
Реализация может выглядеть так:
passport.use( new Strategy(constants.TWITTER_STRATEGY, (req, token, tokenSecret, profile, cb) => { process.nextTick(() => { if (!req.user) { User.findOne({ 'twitter.id': profile.id }, (err, user) => { if (err) return cb(err); if (user) { if (!user.twitter.token) { user.twitter.token = token; user.twitter.username = profile.username; user.twitter.displayName = profile.displayName; user.save(() => { if (err) return cb(err); return cb(null, user); }); } return cb(null, user); }// if no user is found create one const newUser = new User();
newUser.twitter.id = profile.id; newUser.twitter.token = token; newUser.twitter.username = profile.username; newUser.twitter.displayName = profile.displayName;
newUser.save(() => { if (err) return cb(err); return cb(null, newUser); }); }); } else { // when user already exists and is logged in const user = req.user;user.twitter.id = profile.id; user.twitter.token = token; user.twitter.username = profile.username; user.twitter.displayName = profile.displayName;
user.save((err) => { if (err) return cb(err); return cb(null, user); }); } });}), );После этого проводится ваша аутентификация и авторизация с Twitter.
Вот что мои комбиниты выглядели на Github после этих шагов Отказ
Установить локальную аутентификацию и авторизацию
Следующим шагом является аутентификация на месте. На самом деле это не так много, так как мы уже создали окружающую среду.
- Обновите свою схему пользователя для локального, определяя электронную почту и пароль
- Добавьте BCRYPT-NODEJS Пакет для защиты паролей
- Добавьте хеширование и проверку методов пароля к вашей схеме
- Определите маршруты. Этот процесс всегда разъясняет то, что я действительно хочу реализовать
У меня была главная проблема, которую я мог решить только после многих часов поиска. Вот пример из Документы :
app.get('/login', function(req, res, next) { passport.authenticate('local', function(err, user, info) { if (err) { return next(err); } if (!user) { return res.redirect('/login'); } req.logIn(user, function(err) { if (err) { return next(err); } return res.redirect('/users/' + user.username); }); })(req, res, next);});Передача в аутентификации в функции обратного вызова предоставлена достаточная гибкость для отображения ошибок. Но очень важно явно создавать сеанс с Войти () Действительно
- Обязательно отличайтесь в маршрутах между регистрацией и входом!
- Я установил EJS в виде двигателя View, чтобы на самом деле быть в состоянии проверить мою регистрацию и входить в систему правильно и эффективным
- Создайте маршрут выхода из системы, это уничтожает вашу сессию
Я провел так много часов по ошибке, которую я хочу отобразить его здесь: MongooseError: отказаться от ObjectId не удалось значение “favicon.ico” на пути “_id”
Я решил его с помощью проверки все промежуточное программное обеспечение, которая имела серьезную ошибку и маршруты. Оказалось, что устанавливая маршрут к (‘/: PID’) не является хорошим при работе в разработке.
Проверьте мой коммит на Github после задней настройки.
Конечно, на данный момент задняя часть не идеальна. Но это достаточно стабильно, чтобы перейти на следующий шаг, интерфейс.
Дела, которые необходимо сделать:
- Используйте проверку с жой
- Написать тесты подразделения
Внешний интерфейс
Думаю, прежде чем делать!
Прежде всего подумайте о том, что вы хотите создать. Вытягивайте несколько эскизов, чтобы визуализировать то, что вы хотите построить.
Затем рассмотрите соответствующие рамки. Я выберу React.js и государственная библиотека управления Redux Отказ Размер этого приложения делает не Обязательно требуют использования redux.
Я хочу построить его как один опыт страницы. Я хочу иметь масштабируемость, и мне нравится практиковать использование redux. Итак, это хорошая подгонка.
Начните планировать все …| думать в реакции Отказ
Необходимая установка с Babel и WebPack
Важно осознавать, что Бабел и WebPack не слишком сложны, чтобы настроить его самостоятельно. Есть так много учебных пособий за то, что вы можете сделать это легко.
- Добавить Babel для реагирования и ES2015: Добавьте Babel-Preset-React Babel-Preset-ES2015 на ваши зависимости DEV для компиляции JSX в JS и имеют все функции ES6.
- Обновите свой .babelrc файл
- Обновите свой WebPack Config и добавьте React – Hot-Loader упаковка
Сначала я хочу структурировать мой интерфейс без задней части, чтобы соединить весь интерфейс с задней частью в конце. Это потому, что сейчас я не знаю, как будет выглядеть моя реализация Redux. Таким образом, постепенно подключение к задней части не будет эффективным.
- Реструктурировать свой нынешний app.js в собственную папку
- Создайте новое App.js в качестве точки входа и предоставьте Основной код настройки Для рендеринга простой страницы
- Получите настройку. Установите React-Router, WebPack-Dev-Server и React и React-Dom Пакеты
- Открытие страницы на порте Dev-Server должна отображать свой React Component
Вот что мои комбиниты выглядели на Github после этих шагов Отказ
Составные компоненты
Я набросал все на бумаге и пришел к выводу, что мне нужно построить 14 компонентов:
- Компонент приложения, который ходит все
- заголовок
- нижний колонтитул
- боковая панель
- Регистрация, логин и компонент в социальных сетях
- Домашний экран
- Список всех опросов
- дисплей одного опроса
- Компонент для опроса и это ответы
- Ответы как список
- график
- Страница 404
Этот макет был для начала и должен дать обзор. Очень естественно адаптировать компонентную структуру, когда приложение развивается.
Конструкция и сборки
- Я выкладываю все компоненты и стилизовал их с Материализировать Отказ Материализация – это адаптивная конструкция.
- Помните, что стиль с реакцией более сложный, чем укладка нормальных элементов HTML. Для простоты причин я исправил все с помощью встроенной стайлинга на сам компонент.
Кончик: Для 100ВХ на основе вашего основного контента используйте этот встроенный стиль на Div. Он идеально подходит к материализации Flexbox:
style={{ display: 'flex', minHeight: '100vh', flexDirection: 'column',}}- Когда вы создаете компоненты, вы ощупься о том, как вам нужно структурировать ваше государственное управление с React и Redux
Проверьте мой коммит на Github После того, как компоненты построены и в стиле
- Теперь мы должны настроить React Router, чтобы получить основную функциональность и ощущение приложения
- Включить
HOLILLAPIFALLBAK: TRUEНа вашем сервере WebPack DEV для обеспечения правильной маршрутизации с маршрутизатором RACT - добавить состояние и его управление к компонентам
- Поймите, что redux может быть хорошим следующим шагом
Вот список болезненных учащихся, которые я должен был пройти на протяжении всего этого процесса:
- Для доступа к свойствам объекта используйте кронштейн вместо нотации DOT. Например: JavaScript
answers.concat (this.refs [temp] .value) - Импортировать все как
* (Импорт * как опросы из './ducks/polls';)от уток. В противном случае это не будет работать - Я часто читаю в не Используйте индекс функции карты как ключевое значение для компонента. Однако при рендеринге с
Onchangeи генерируя уникальный ключ, вход теряет фокус и не работает должным образом. Например:(const.state.answers.map ((ответ, ind) = > {return (<ключ div = {ind}>) - Когда вы повторяете на массиве объектов и хотите изменить свойства на объекте, который вы должны вернуть объект. Например:
return {Ответ: Ответ.answer, голосов: 0};Мне потребовалось 4 часа, чтобы понять?
Принципы redux:
- Единый источник правды
- Государство только для чтения
- Изменения выполнены с чистыми функциями
Имейте в виду, что локальное состояние не нужно принимать участие в Redux, когда его состояние не используется другими компонентами.
- Добавьте React-redux и redux пакеты
- использовать Утки структура управлять файлами Redux лучше
- Создайте магазин в Redux и заверните свое приложение для рендеринга в
ПровайдерТег от React-redux - Подключите состояние к вашему приложению с
соединять - Добавьте Redux devtool отлаживать быстрее
Теперь это состояние доступно через Redux, пришло время создавать обработчики событий и правильно сделать все. Теперь вы должны подтвердить свой ваш Пропорпы также.
Визуализация
Для отображения результатов, которые я выбрал между:
После скидки всех документов и пробуя несколько вещей, я закончил выбрать React-Google-Charts. Google предоставляет множество вариантов, и устройство Reactper позволяет легко реализовать в приложении React.
С операторской оберткой этот шаг был супер легким и быстрым.
const resultChart = (props) => { basic = [['Answer', 'Votes']]; (() => props.poll.answers.map(ans => basic.push([ans.answer, ans.votes])))(); return ( );};Подключите передний конец к экспресс-концу с помощью React Router
Рендеринг клиентской и серверной стороне
Поскольку это было мое первое настоящее приложение для полного стека, подключением передней и задней части был загадкой для меня. Я нашел хороший ответ на мой вопрос о переполнении стека.
Подвести итоги и процитировать ответ Stijn :
Подробнее о его комментариях нажмите здесь Отказ
В конце концов я пошел с уловным решением: см. В моем Marals.js Файл Отказ
//routes.jsrouter.get('/*', (req, res) => { const options = { root: `${__dirname}/../../public/`, dotfiles: 'deny', }; res.sendFile('index.html', options);});Было легко и быстро реализовать и охватывает основные проблемы.
Обслуживание всего вместе
Чтобы понять, что лучший способ – посмотреть на мой package.json file. .
Сценарии говорят:
"scripts": { "start": "node src/serverSide/server.js", "serve": "babel-node src/serverSideES6/server.js", "dev": "npm-run-all --parallel dev:*", "dev:client": "webpack-dev-server --hot", "dev:server": "nodemon src/serverSide/server.js", "build": "npm-run-all --parallel build:*", "build:client": "webpack --progress", "build:server": "babel src/serverSideES6 --out-dir src/serverSide" }, построить Сценарий создает файлы на стороне клиента и сервера.
- Он компилирует все мои es6 node.js в ES5, поэтому Heroku может прочитать его также
- WebPack запускает соединение и транспиловать клиентскую сторону, такую как от ES6 до ES5, и JSX в JavaScript.
dev Сценарий обслуживает все в среде развития и (горячей) перезагрузки. Все как можно быстрее и гладкое, насколько это возможно, при изменении кодовой базы.
Начать Скрипт на самом деле запускает задний сервер, который также потребляет встроенный и подключенный интерфейс HTML, CSS, JavaScript, представляющий все приложение.
Развертывание
Для развертывания приложения Heroku еще раз оказался способом идти.
Используя Heroku Cli , Heroku Logs Команда много помогает. У меня всегда были проблемы с настройкой моего приложения на платформе. Но после решения всех ошибок журналы показывают, становится очень легко.
Всегда важно:
- Помните, что Devdependons не установлены
- Используйте адекватный сборки. В этом случае это для Node.js
- Есть
Начатьскрипт или определить один в вашем процепке - Обязательно протолкните правую ветку из правого репозитория
Заключение
Как видно, моя документация для этой статьи станет хуже и хуже с прогрессом приложения. Это связано с тем, что я получил полностью перегружено Redux. Я сделал другие проекты на стороне и не смог отслеживать.
Но не волнуйся! Я попытался назвать мои коммиты как можно скорее. Таким образом, вы можете пройти все коммиты для деталей в моем репозитории. Посмотреть Комбинирует здесь Отказ
Если у вас есть вопросы, не стесняйтесь спрашивать:)
- Доступен репозиторий на Github здесь Отказ
- Живая версия результата доступна здесь Отказ
- Изучение и цифры доступны здесь Отказ
Многие, большое спасибо Эдо Ривай , который дал очень ценные советы по пути.:)
Спасибо за чтение моей статьи! Не стесняйтесь оставить какие-либо отзывы!
Оригинал: “https://www.freecodecamp.org/news/building-the-free-codecamp-voting-app-1a6fdce1f4a8/”