Редизайн моего сайта-портфолио

В настоящее время я занимаюсь перепроектированием своего веб-сайта с портфолио и хотел использовать фреймворк Hugo, поскольку он молниеносно создается, имеет удобную функцию ведения блога и не требует особого обслуживания.

Причина изменения дизайна и перемещения фреймворка в том, что исходный сайт был просто написан с использованием html, css и js. Я хочу перевести веб-сайт на современный фреймворк, который проще в обслуживании, и применить логику на основе компонентов там, где это необходимо.

Почему Хьюго?

Поскольку я документирую свое путешествие по разработке, Хьюго предлагает прекрасную возможность для полноценной функции блога. Создать новую публикацию так же просто, как запустить hugo new blog posts/title, который затем создает всю правильную маршрутизацию, а с помощью разметки макетов можно даже обрабатывать такие вещи, как теги, автор, дата создания, разбиение на страницы и порядок.

Проблема со старым кодом:

//index.html
  <div>
      <a href="https://dashboard.featurepeek.com/peek/k5zh70zl#/">
        <div class="beatjuice portfolio-proj zoom bottom-margin_10">
      </div>
      </a>
      <p class="text-center port-desc_mw bottom-margin_10">A beat machine made with React and Howler.js
      </p>
    </div>

    <div>
      <a href="https://fork-it-all.herokuapp.com/">
        <div class="forkitall portfolio-proj zoom bottom-margin_10">
    </div>
      </a>
      <p class="text-center port-desc_mw bottom-margin_10">Forkitall - A single page React app that allows users
        to share
        their twists on various recipes. Pulls data from <a
          href="https://www.themealdb.com/api.php">TheMealDB.com</a>
      </p>
    </div>

    <div>
      <a href="https://github.com/AndrewRLloyd88/jungle-rails">
        <div class="jungle portfolio-proj zoom bottom-margin_10"></div>
      </a>
      <p class="text-center port-desc_mw bottom-margin_10">Jungle - A mini e-commerce application built with
        Rails 4.2
      </p>
</div>
//style.css

/* Portfolio Elements */

.listkeeper {
  background-image: url('./images/listkeeper.jpg');
  background-size: cover;
}

.beatjuice {
  background-image: url('./images/beatjuice.jpg');
  background-size: cover;
}

.phaserpong {
  background-image: url('./images/pong.jpg');
  background-size: cover;
}

.jeopardy {
  background-image: url('./images/jeopardy.jpeg');
  background-size: cover;
}

.forkitall {
  background-image: url('./images/cookdinosaur.svg');
  background-size: cover;
}

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

По умолчанию Hugo не имеет никаких настроек для пакетов webpack или npm.

Первый шаг - запустить npm init -y для создания package.json.

Следующим шагом будет установка всех зависимостей npm i --save-dev babel-loader @babel/core webpack @babel/preset-react react react-dom npm-run-all

Я начал с чтения приведенной ниже статьи в качестве отправной точки:

Отправная точка: как добавить сценарий реакции в hugo

Я использовал Build Websites With Hugo Брайана П. Хогана в качестве руководства по Hugo, поэтому я обратился к главе 7, Управление активами с помощью каналов, чтобы правильно настроить мои скрипты package.json:

"build": "npm-run-all webpack hugo-build",
    "hugo-build": "hugo --cleanDestinationDir",
    "hugo-server": "hugo server --disableFastRender",
    "webpack": "webpack",
    "webpack-watch": "webpack --watch",
    "dev": "npm-run-all webpack --parallel webpack-watch hugo-server"

npm run build встраивает текущую версию веб-сайта в папку / public. Я использую npm run dev, который вместе с пакетом npm-run-all используется для сборки, запуска webpack, запуска сервера hugo и отслеживания изменений.

Сначала я настроил свой webpack.config.js следующим образом:

const path = require('path');

module.exports = {
  entry: './themes/arlmediaTheme/assets/js/index.js',
  output: {
    filename: 'app.js',
    path: path.resolve(__dirname, 'themes', 'arlmediaTheme', 'assets', 'js'),
  },
};

Точкой входа был index.js в файле js, который я настроил для быстрого тестирования с использованием пакета Axios и API Kanye Rest. Index.js находился в моем шаблоне hugo в каталоге arlmedia-portfolio/themes/arlmediaTheme/assets/js/.

Содержимое JS файла:

import axios from 'axios';
import lunr from 'lunr';

axios.get('https://api.kanye.rest').then((res) => {
  console.log(res.data);
});

Этот файл был перенесен обратно в уменьшенную версию с синтаксисом до ES6 в файл app.js, который находится в каталоге / public.

Чтобы работать с React, поскольку он использует синтаксис JSX, мне также пришлось включить babel и настроить файл конфигурации. Следуя указаниям руководства, я установил свой файл babel.config.js в корне моего проекта следующим образом:

module.exports = function (api) {
  api.cache(true);
  const presets = [['@babel/preset-react']];
  const plugins = [];
  return {
    presets,
    plugins,
  };
};

Этот коммит показывает изменения, которые я внес в конфигурацию, и какие пакеты я включил, чтобы несколько файлов стиля React работали с Hugo.

Основные изменения, которые я внес в webpack.config.js:

const path = require('path');

module.exports = {
  entry: './themes/arlmediaTheme/assets/js/index.js',
  output: {
    filename: 'app.js',
    path: path.resolve(__dirname, 'themes', 'arlmediaTheme', 'assets', 'js'),
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
          },
        ],
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
        include: /flexboxgrid/,
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: ['file-loader'],
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
};

Это позволило файлу index.js сгенерировать уменьшенную версию, которая была перенесена из синтаксиса ES6 обратно в ES4 и запущена на сервере hugo.

Использование React превратило запутанный повторяющийся код в CSS и JS, о котором я поделился выше, в следующее:

import React, { useState, useEffect } from 'react';
import { projectData } from './projectData';

export default function main() {
  return (
    <div className="project">
      {projectData.map((project, i) => (
        <div className="project-inner">
          <div className="project-container">
            <div className="project-description">
              <div className="project-desc-text">
                <p className="desc">{project.description}</p>
                {project.frontend && (
                  <p className="stack-type">
                    <span className="stack-type-title">Frontend:</span>
                    <div className="stack-row">
                      {project.frontend.map((icon, i) => (
                        <span className="stack-icon">
                          <img
                            className="stack-image"
                            src={icon}
                            title={project.frontendNames[i]}
                          ></img>
                        </span>
                      ))}
                    </div>
                  </p>
                )}
                {project.backend && (
                  <p className="stack-type">
                    <span className="stack-type-title">Backend:</span>
                    <div className="stack-row">
                      {project.backend.map((icon, i) => (
                        <span className="stack-icon">
                          <img
                            className="stack-image"
                            src={icon}
                            title={project.backendNames[i]}
                          ></img>
                        </span>
                      ))}
                    </div>
                  </p>
                )}
                {project.test && (
                  <p className="stack-type">
                    <span className="stack-type-title">Test:</span>
                    <div className="stack-row">
                      {project.test.map((icon, i) => (
                        <span className="stack-icon">
                          <img
                            className="stack-image"
                            src={icon}
                            title={project.testNames[i]}
                          ></img>
                        </span>
                      ))}
                    </div>
                  </p>
                )}
                {project.deployment && (
                  <p className="stack-type">
                    <span className="stack-type-title">Deployment:</span>
                    <div className="stack-row">
                      {project.deployment.map((icon, i) => (
                        <span className="stack-icon">
                          <img
                            className="stack-image"
                            src={icon}
                            title={project.deploymentNames[i]}
                          ></img>
                        </span>
                      ))}
                    </div>
                  </p>
                )}
              </div>
            </div>
            <img className="project-image" src={project.image}></img>
          </div>
          <div className="project-control-panel">
            <p className="project-name">{project.name}</p>
            <div className="project-buttons">
              {project.github !== '' && (
                <button
                  onClick={() => {
                    window.location.href = `${project.github}`;
                  }}
                >
                  Code
                </button>
              )}
              {project.demo !== '' && (
                <button
                  onClick={() => {
                    window.location.href = `${project.demo}`;
                  }}
                >
                  Demo
                </button>
              )}
            </div>
          </div>
        </div>
      ))}
    </div>
  );
}

Этот код в конечном итоге легче поддерживать, он извлекается из объекта projectData, который я определил в следующей схеме:

export const projectData = [
  {
    name: 'MB-WYSIWYG Text Editor',
    description:
      'A Rich Text Editor built for Mintbean’s Build Your Own Text Editor hackathon.',
    image: '/images/projects/wysiwyg.png',
    github: 'https://github.com/AndrewRLloyd88/mb-text-editor',
    demo: 'https://mb-wysiwyg-text-editor.netlify.app/',
    frontend: [react, typescript, css3, materialui],
    backend: null,
    test: null,
    deployment: [netlify],
    frontendNames: ['React', 'TypeScript', 'CSS3', 'MaterialUI'],
    backendNames: null,
    testNames: null,
    deploymentNames: ['Netlify'],
  },
  //more projects are below in the array

Переменные из значков импортируются в верхнюю часть этого файла данных. Затем этот объект данных и все свойства проекта отображаются в index.js. В будущем можно будет провести дальнейший рефакторинг, чтобы разделить все элементы на отдельные компоненты. В целом это намного проще в обслуживании, поскольку мне нужно было бы только изменить данные моего проекта в одном месте, а не копировать и вставлять HTML-контент. Об остальном Map позаботится в файле index.js.

Готовый результат:

Как добавить более одного файла ввода стиля React

Мне нужно было запустить два сценария React: один для моих проектов, а другой - для моих навыков, чтобы они отображались аналогично тому, как описано выше. При такой настройке у меня в настоящее время не было возможности определить два файла ввода и вывода. После небольшого исследования я наткнулся на этот полезный пост:

Как добавить более одного пути в webpack

Я установил два модуля следующим образом:

И настройте мою конфигурацию webpack, чтобы использовать две точки входа и сгенерировать два выходных файла:

module.exports = {
  entry: {
    index: './themes/arlmediaTheme/assets/js/modulea/index.js',
    projects: './themes/arlmediaTheme/assets/js/moduleb/projects.js',
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'themes', 'arlmediaTheme', 'assets', 'js'),
  },
  //...

Идея состоит в том, что эта установка может принимать index.js и projects.js из пути './themes/arlmediaTheme/assets/js/[your module] и выводить файлы в другом месте, main.js и projects.js, которые выводятся в каталоге / js, являются уменьшенными и перенесенными версиями JSX. файлы. Вышеупомянутый метод рассматривается как обходной путь, но дает правильные результаты для моих нужд.

Ошибки ограничения SVG

Я также столкнулся с некоторыми проблемами при использовании SVG сначала из-за пользовательской настройки с помощью webpack. Первоначально все мои ресурсы SVG возвращались 404, несмотря на правильный путь. В какой-то момент много файлов .SVG создавалось с уменьшенным именем, и браузер явно не получал правильные файлы:

module.exports = __webpack_public_path__ + "images/code.61e3a3939c2f93f30ac21419625c9a4f.jpg"

Вот как выглядел путь к файлу. Чтобы исправить это, я немного исследовал StackOverflow:

Использование изображений с Webpack React не сработает

В этой статье я рекомендовал удалить загрузчик URL-адресов и настроить svg-url-loader в config.js webpack:

{
        test: /\.svg$/,
        use: [
          {
            loader: 'svg-url-loader',
            options: {
              limit: 10000,
            },
          },
        ],
      },

Это решило первую проблему, но у меня все еще было несколько файлов .SVG, которые не загружались. Тогда я немного покопался и нашел эту статью:

Возрастающий предел при возникновении ошибки 404 с SVG

Я взял ответ из этой статьи и увеличил лимит в параметрах параметров:

{
        test: /\.svg$/,
        use: [
          {
            loader: 'svg-url-loader',
            options: {
              limit: 1000000,
            },
          },
        ],
      },

И привет!

Выводы, которые я получил от обновления моего веб-сайта, были огромными. Есть еще определенные вещи, которые я хотел бы изучить с помощью Webpack, я хотел бы получить немного больше информации о настройке веб-пакета, а также о тонкостях, чтобы полностью понять, что означают параметры и какие настройки нужно настроить.

Было очень полезно изучить другой фреймворк в Hugo, сайт отличается высокой производительностью и молниеносно создается, а конвейер контента обладает большой гибкостью.

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

Я хотел бы найти способ автоматически вносить изменения Public в мой хостинг SiteGround и изучил CircleCI, Jenkins и другие методы для развертывания, но я еще не определился с тем, чтобы прямо сейчас развернуть плавное и автоматическое развертывание через SiteGround, так что это кое-что, что я хотел бы провести немного больше, и если у кого-то есть предложения, не стесняйтесь обращаться к нам!

Первоначально опубликовано на https://arlmedia.ca 8 февраля 2021 г.

Об авторе

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

Он выпускник учебного курса по веб-разработке Lighthouse Lab, волонтер и член сообщества mintbean.io.

Он изучил и реализовал различные навыки, в том числе

  • HTML5
  • Машинопись
  • JavaScript
  • Рубин на рельсах
  • CSS3
  • MySQL / PostgreSQL
  • Бутстрап
  • MaterialUI
  • Реагировать
  • Redux

До посещения буткемпа его сферами деятельности были: администрирование, чтение лекций, производство фильмов и пост-продакшн, а также обслуживание клиентов в различных секторах.

Он хотел бы подключиться к возможностям и найти способ привнести свои знания и энтузиазм в ваши проекты!