JavaScript is changing more rapidly than its runtime environments can keep up with. For instance, we will be using the import
and export
keywords (which are part of ES6 modules) in this project. These keywords were not supported in Chrome (or other browsers) until recently.
To work around this and similar issues, the community has developed programs that allow JavaScript to be written using the latest features and transformed into an earlier version that will run seamlessly on the browser. These programs are typically called “transpilers” and are part of a “build tool.” In addition to a transpiler, a build tool typically includes a bundler that combines several JavaScript files into a single (minified) .js
file or breaks a very large file into several (minified) chunks to improve initial load time (a process known as code splitting), among other utilities.
There are many build tools available, and it is common practice to use one for web development. In this chapter, we will use a build tool called Vite (a French word for “fast,” pronounced /vit/
).
If you’re interested in learning more about this and related topics, the following resources are recommended:
You must have Node and pNPM installed on your computer. Please refer to logistics section of the syllabus for more details.
We will create a new Vite project using the pnpm create vite
command followed by the name of our project, which we will call todo-app
.
When prompted, select Vanilla
for the project framework and JavaScript
for the variant.
Now, we will navigate to our newly created project directory and open it in VSCode.
Notice that Vite has created the following files:
We will explore these files. However, let’s first demystify the scaffolding process:
pnpm
is a package manager for Node.create vite
loads a command-line tool that scaffolds a Vite application.todo-app
is the name of our application.vanilla
is a term developers use to refer to using plain JavaScript instead of a library like React.Let’s explore the template project created by Vite:
.gitignore
is a minimal list of files and folders to be ignored when Git tracks this project.javascript.svg
and vite.svg
are Scalar Vector Graphics (SVG). These graphics are displayed in the sample web app that comes in the template project.index.html
is a minimal boilerplate HTML file similar to those we created in earlier chapters.main.js
is a minimal JavaScript file linked to the index.html
similar to those we created in earlier chapters. It makes use of counter.js
which implements a simple counter!style.css
is linked to the index.html
file and provides minimal styling similar to those we created in earlier chapters.package.json
holds metadata relevant to the project. It is also used by pNPM for managing the project’s dependencies, scripts, version, and more. We will explore this further in a future chapter.Let’s glance over the content of package.json
:
Notice the section under “scripts.” We can use the keywords under the script to run the commands associated with them. First, however, you must install the “dependencies” for this project. In this case, the only dependency is the vite
library.
Open the terminal and change the directory to todo-app
folder. Then, run the following command.
It will take a moment for the dependencies to be installed. Once done, you will have a folder, node_modules
, added to todo-app
. This folder contains the dependencies of your application (and their dependencies).
Make sure to always exclude the node_modules
folder from your Git repository. In this case, it is already included in your .gitignore
file.
Additionally, a file, pnpm-lock.yaml
, is added to the todo-app
folder. This file contains the dependency tree of your application (its dependencies, and the dependencies of the dependencies, etc.).
The pnpm-lock.yaml
is automatically generated and modified. Therefore, you should never directly edit it.
Make sure to include pnpm-lock.yaml
in your Git repository. You need this file to get the exact dependencies your project is built on for any subsequent installs.
You are now ready to “run” the application. In the terminal, enter the following command:
The command will spin up a local server to run your web application at http://localhost:5173/. Open your browser and visit the website.
To stop the server, you must halt the process by pressing Ctrl
+ C
in the terminal.
Aside-1: To run the web application, Vite uses your computer as a server. By default, this server is not accessible over the web; you can only access it on your local computer. That’s where the name localhost comes from. To learn more, check out What is Localhost? Explained for Beginners.
Aside-2: The number 5173
is a port number. In computer networking, a port is a communication endpoint. Port numbers start from 0
. The numbers 0
to 1024
are reserved for privileged services (used by the operating system, etc.). For local development, we usually use numbers ≥ 3000
. By default, Vite runs the web application under development on port 5173
. Note that if the port is already being used, Vite will automatically try the next available port, so this may not be the actual port the server ends up listening on.
Aside-3: Vite comes with several goodies, including Hot Module Replacement, which efficiently reloads the page in the browser as you update the source code. (So, you don’t have to refresh the page manually every time you make a change.)
Let’s clean up the boilerplate code that was generated by Vite. We’ll delete the counter.js
file and the two SVG files, vite.svg
and javascript.svg
. We’ll also clear the contents of main.js
and style.css
.
Download the following favicon.png and add it to the public
folder.
src
directoryWe’ll create a src
directory and move the main.js
file into it.
We’ll import the CSS file in main.js
and include some sample code to display “Hello World!” in the browser.
Next, we’ll update the index.html
file to reflect the changes. We’ll link to our favicon and change the title of the page to “ToDo App”. We’ll also update the script
tag to point to the main.js
file in the src
directory.
Run the app with the following command.
Then point your browser (Firefox Developer Edition) to http://localhost:5173/ to view the app.
Aside: In this section, we used JavaScript to add style and HTML elements to the index.html
file. The index.html
file itself only contains a single div
element with an id
of app
. This demonstrates how JavaScript can be used to dynamically modify the content and appearance of a webpage.
Next, we will install Tailwind CSS. We will use pnpm to install it as a development dependency.
Tailwind CSS is a utility-first CSS framework that provides pre-built CSS classes to help developers build user interfaces more efficiently. It is designed to solve the problem of having to write repetitive CSS code for common UI patterns, such as margins, paddings, and typography, by providing a set of reusable utility classes that can be combined to achieve the desired styles.
The advantages of using Tailwind CSS over writing plain CSS files are many. First, Tailwind CSS eliminates the need to write custom CSS for every UI element, which saves a significant amount of time and effort. Second, it promotes consistency in design by providing a standardized set of CSS classes that can be used across projects. Third, it reduces the file size of CSS by only including the necessary styles rather than a large set of CSS rules that may not be used. Fourth, it makes responsive design easier with its built-in responsive utility classes. Finally, Tailwind CSS allows for easy customization by enabling developers to add or modify the existing CSS classes to fit their specific needs.
In contrast to traditional CSS frameworks like Bootstrap, which provide pre-built components and styles, tailwindcss focuses on providing utility classes that can be used to build custom designs. This approach gives developers more flexibility and control over the design of their applications while still providing a consistent and maintainable codebase.
After installing tailwindcss, we will need to initialize it.
This command creates two files in our project root: tailwind.config.js
and postcss.config.js
files. The postcss.config.js
is the configuration of PostCSS, which is a dependency of Tailwind. In case this file was not created, you can create it manually with the following content:
Aside: npx
is a command-line utility that lets users run Node.js packages without installing them globally on their system. When a command is run with npx
, it searches for the package locally in the project’s node_modules
directory. If it is not found, it automatically downloads and installs the package before running it. This can be helpful for running one-time or infrequently used commands without needing to install the package globally on the system.
The tailwind.config.js
file is the configuration file for tailwindcss, which allows us to customize the default settings of tailwindcss. Here, we will configure Tailwind CSS to scan the HTML and JavaScript files in our project for classes to generate the necessary CSS.
Next, we will include tailwindcss in our CSS. We will do this by adding the following lines to our style.css
file.
To check that our setup works, update the main.js
as follows:
Run the app and observe the changes!
Next, we will install Prettier as a development dependency.
Prettier is a code formatter that automatically formats your code according to a set of rules. It can be used with a variety of programming languages, including JavaScript, CSS, HTML, and more. Prettier solves the problem of inconsistent coding style, which can make code difficult to read and maintain. By applying a consistent formatting style to your code, Prettier can improve code readability and make code easier to understand for developers. Prettier can be integrated with most code editors and build tools, allowing for automatic formatting during development and deployment.
Then, we will create a .prettierrc.json
file in the root of our project to configure Prettier.
These Prettier configurations determine how Prettier formats the code.
semi
: determines whether to use semicolons at the end of statements.trailingComma
: determines whether to include a trailing comma after the last element in an array or object.singleQuote
: determines whether to use single quotes or double quotes for strings.printWidth
: determines the maximum line length before Prettier wraps the code to a new line.tabWidth
: determines the number of spaces to use for indentation.endOfLine
: determines the type of line ending to use for the file.These configurations ensure that the code is formatted consistently and in a readable manner.
Next, create a .prettierignore
file to let Prettier and editors know which files not to format.
When we use Vite to build the site, it creates the build artifacts in the dist
folder. We have added the dist
folder in the .prettierignore
file to avoid formatting it.
Finally, add this command to the scripts
section of the package.json
file:
Now you can run Prettier from the terminal:
When it’s time to deploy your application for production, you must first “build” the appropriate production bundle to be served over a hosting service.
Stop the development server and run the following command:
The build command will generate an optimized build of your web application, ready to be deployed. The generated artifacts will be placed in the dist
folder.
Open the dist
folder and explore its contents. To preview the application in production, you can use the following command to serve it locally from the dist
folder:
The production-ready app will be served at http://localhost:4173/.
When it’s time to deploy the application for production, the contents of the dist
folder need to be deployed to a web server or hosting service. This can be done manually by copying the contents of the dist
folder to the server or by using a deployment tool like rsync
or scp
. Some hosting services, like GitHub Pages or Netlify, can also be configured to automatically deploy the contents of the dist
folder when changes are pushed to the Git repository.
If you haven’t already done so, initialize a local Git repository and commit your code.
We will deploy this app to GitHub pages. Create a GitHub repository and push your local code to it. Next, on your local repository, create the vite.config.js
file with the following content:
Replace REPO_NAME
with the name of your repository!
Next, create a .github
folder. Add a subfolder workflows
to .github
. Finally, add a deploy.yml
file to this subfolder with the following content:
Before pushing these changes to GitHub, update the settings of your GitHub repository to use “GitHub Action” for deploying the app to GitHub Pages.
Push your code to the GitHub repository. This will trigger a build process that will result in deploying your app. From this point on, every time you make changes to your code on the main
branch and push those changes to GitHub, the new app will be automatically deployed.
Note: The deploy.yml
configuration file above uses GitHub Actions to deploy a site to GitHub Pages. For more information, refer to the article “GitHub Pages now uses Actions by default”.