Please read this section at least one day prior to the seminar. This section outlines what you are expected to know, be able to do, or prepare in advance. Following these instructions will help you get the most out of the seminar and ensure smooth participation.
Before the start of the practical, you should be able to:
This slide applies to you only if you plan to use your own computer for the practical.
Before the start of the practical, make sure that:
npm create vite@latest
Vite is a blazing fast frontend build tool powering the next generation of web applications.
Vite is a (zero-configuration) build tool. It is opinionated and comes with sensible defaults out of the box. Vite can be installed using npm. npm is distributed with Node.js. We employ vite to create a new project using "npm create" command, which is similar to "composer create-project" command.
npm create vite@latest
Select Vanilla as a framework and TypeScript variant. Take a look at:
Take a look at file names in "dist" directory. Why are there some "random" suffixes for css and js files?
TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.
Set initial counter value to "0" in counter.ts file.
setCounter("0");
What should happen and what happened?
Create a new entry point "articles.html", a new main TypeScript file "articles-main.ts" and a service file "articles-service.ts". Include "articles-main.ts" from "articles.html". Create article service, return mocked article list, and implement renderer.
// articles-main.ts
import { fetchArticles } from './articles-service.ts'
async function renderArticles() {
const articles = await fetchArticles();
/* TODO: Render articles */
}
renderArticles()
// articles-service.ts
interface Article { identifier: string; title: string; }
export async function fetchArticles(): Promise<Article[]> {
/* TODO */
}
Continue to the next slide once you are done >>>
...
Congratulations, if you have followed the instructions, you have just reached the end of this exercise.
Unless developing single-page-application we may need multiple entry files. It works just fine for "dev", but same is not true for "build".
Build tools often provide tool-specific way of configuration. In case of Vite, we can employ vite.config.js file to configure multiple entry points.
// vite.config.js
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
articles: resolve(__dirname, 'articles.html'),
},
},
}});
Semi-random configuration classification:
We can provide the configuration using a configuration file, like JSON or YAML file. We can also utilize environment variables. We can also employ version of .env file.
In general, configuration files do not belong into a versioning system.
Vite supports .env files and environment variables out of the box. Selected variables:
To prevent accidentally leaking env variables to the client, only variables prefixed with VITE_ are exposed to your Vite-processed code
Introduce .env file with "VITE_LIST_OWNER" variable and use it in the "article-main.ts" file as a prefix to the article list.
What, why, how?
We utilize Prettier to take care of code formatting. While Prettier works with multiple source types, including PHP, we utilize it only in scope of Vite project. It may be useful to consider IDE integration.
Another step is to utilize ESLint which statically analyzes the code.
While it is possible to run both tools using npx, we integrate both tools into our Vite project.
npm install --save-dev prettier
We can employ prettier.config.ts file to customize Prettier's options. Note that we can use different files to configure Prettier. You can execute prettier manually using:
npx prettier -w .
ESLint can be executed on demand or during the development to provide instantaneous feedback. Besides ESLint we also need plugins, for different languages, and configurations. We utilize ESLint and typescript-eslint.
npm install -D eslint @eslint/js
# Integration with Typescript
npm install -D typescript typescript-eslint
# Integration with Prettier
npm install -D prettier eslint-plugin-prettier eslint-config-prettier
# Global identifiers from different JavaScript environments
npm install -D globals
ESLint utilizes eslint.config.mjs, or other file depending on your setup, for configuration and .eslintignore to ignore directories. Alternatives are JSON file, YAML file, part of package.json, eslint.config files, etc.. We use "eslint.config.mjs" file, see following slide.
Add following line to script section in your package.json file to execute ESLint in current directory.
"lint": "eslint . --fix"
// eslint.config.mjs
import eslint from "@eslint/js"
import globals from "globals"
import tseslint from "typescript-eslint"
import { defineConfig } from "eslint/config"
// https://github.com/prettier/eslint-plugin-prettier
import prettier from "eslint-plugin-prettier/recommended"
export default defineConfig([
{
// This is a special construct and must be in a separate section.
// https://github.com/eslint/eslint/discussions/18304
ignores: ["**/dist/*"],
},
eslint.configs.recommended,
tseslint.configs.recommended,
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
},
prettier,
]);
You may also know it as "hot deployment", "hot reloading", "hot swapping".
Hot deployment is the process of adding new components (such as WAR files, EJB Jar files, enterprise Java beans, servlets, and JSP files) to a running server without having to stop the application server process and start it again.
Hot Module Replacement (HMR) is capable of replacing JS code without the need of a reload. You can integrate with HRM using build tool API, e.g. Vite's API. This integration is usually handled by a framework, but we can interact with it as well. It works on level of modules ~ individual files ~ HMR boundary.
// service.ts
export const createService = () => {
return {
data: { counter: 0 },
value() { return this.data.counter },
increase() { this.data.counter += 1 }
}
}
Create "hmr-main.ts" as a copy of "main.ts", just to keep the original file around. Next use the new service in "main.ts".
import { createService } from "./service";
// ...
let service = createService();
const setupCounter = (element: HTMLButtonElement) => {
element.innerHTML = 'count is 0';
element!.addEventListener("click", () => {
service.increase();
element.innerHTML = `count is ${service.data.counter}`;
});
};
Do not forget to remove the original import of "setupCounter" function.
We need custom implementation of module reloading.
if (import.meta.hot) {
import.meta.hot.accept(["./service"], ([serviceModule]) => {
// Get next service.
const nextService = serviceModule.createService();
// Move data from old to new.
nextService.data = service.data;
// Replace old with new.
service = nextService;
})
}
Vite has build in server proxy. You can use it to proxy local endpoint to anything.
Works best when combined with Environment Variables in Config.
I appreciate the opportunity (/obligation) to deploy my own application - I believe that many people have never tried it before. But why php? :( I don't know and can't use php - so most of the time I just struggle with the syntax and in the end I end up throwing it to Claude...
Anonymous 2026
Run "build" command and check the output, the "./dist" directory. Would it work when deployed to you home directory at webik?
It is possible to use configuration (variables) in the vite.config.js.
PS: There is no assignment from this practical.