- Tech News Asia
- Overview
- Highlights
- Webpack configuration
- raw-loader
- html-loader
- file-loader
- [style-loader, css-loader, sass-loader and sass-resource-loader](#style-loader-css-loader-sass-loader-and-sass-resource-loader)
- clean-webpack-plugin
- webpack-dev-server
- Single-page web app
- Desktop sidebar -> mobile navbar conversion
- Webpack configuration
A 2-page, static news site on tech startups in Asia. Built with JavaScript, Webpack 5 and Sass. See it live here.
The following webpack plugins were installed:
Imports files as a String. I use it together with insertAdjacentHTML() to render the navbar dropdown button as an svg
HTML element:
import svg from "./hamburger.svg";
let dropdownButton = document.getElementById("dropdown-button-wrapper");
dropdownButton.insertAdjacentHTML("afterbegin", svg);
The result:
By rendering it this way, I can select the svg element in my scss
file and change its color through the fill
style attribute.
Configuration in webpack.config.js
:
module: {
rules: [
{
test: /\.svg$/i,
use: "raw-loader",
},
];
}
Exports HTML as string. That way, I can place the HTML code in a separate file and load it into my JavaScript file as a String variable.
import html from "./navbar.html";
const navbarLoad = () => {
document.body.insertAdjacentHTML("afterbegin", html);
};
This feature was especially useful when rendering different articles - see below
Configuration in webpack.config.js
:
module: {
rules: [
{
test: /\.html$/i,
use: "html-loader",
},
];
}
Converts import/require
statements on a file into a url and places the file in the output directory.
In this case, there is actually no import/require
statement applied directly to files. Instead, the plugin is used by html-loader when reading src
attributes in order to load article images.Example from articles.html:
<figure>
<img src="./img/india.jpg" alt="WhatsApp" />
<figcaption>Photo credit: Venturebeat</figcaption>
</figure>
Configuration in webpack.config.js
:
module: {
rules: [
{
test: /\.(png|jpg|gif|jpeg)$/,
use: "file-loader",
},
];
}
style-loader
, css-loader
, sass-loader
and sass
are used together in order to set styling with Sass.
I added sass-resource-loader
in order to avoid having to import the common.scss file in each of the other scss
files. This file contains a number of Sass variables.
Configuration in webpack.config.js
:
module: {
rules: [
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader",
{
loader: "sass-resources-loader",
options: {
resources: ["./src/common/common.scss"],
},
},
],
},
];
}
Removes/cleans my build folder. I configured it to avoid removing the index.html
and favicon.svg
so that I could keep the meta tags and the favicon:
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ["**/*", "!index.html", "!favicon.svg"],
}),
],
Creates a development server with live reloading. Configuration in webpack.config.js
:
devServer: {
contentBase: "./dist",
hot: true,
},
Having everything on a single page makes loading new content very fast:
I placed the content for all articles in the articles.html file for the sake of simplicity. Each article is wrapped in a section
element with a unique id
attribute:
<section class="article-section" id="china">
<!--code--->
</section>
<section class="article-section" id="india">
<!--code--->
</section>
<!--code--->
article.js then toggles between articles based on their id
:
import html from "./articles.html";
const articleLoad = (articleId = "china") => {
//remove previous article html
let prevSection = document.querySelector("main>section");
if (prevSection) {
prevSection.remove();
}
//get the new article from articles.html based on the id
let doc = new DOMParser().parseFromString(html, "text/html");
document.querySelector("main").appendChild(doc.getElementById(articleId));
//move the viewport to the top of the page
moveTop();
};
On desktop mode, there is a sidebar that enables you to switch between articles. In tablet and mobile, this sidebar moves to the top, after the nav links, and only shown when the dropdown button is clicked:
All screen modes use the same HTML code for the sidebar, and the same JavaScript code to toggle between articles. The only difference lies in the sidebarMobileShow
function, which is only used in tablet and mobile modes to show and hide the sidebar:
const sidebarMobileShow = () => {
//get sidebar
let sidebar = document.getElementsByTagName("aside")[0];
//check if navbar button is toggled to show sidebar
if (
document
.getElementById("dropdown-button-wrapper")
.classList.contains("nav-selected")
) {
//show sidebar
sidebar.style.display = "block";
} else {
//hide sidebar
sidebar.style.display = "none";
}
};