{"id":19565884,"url":"https://github.com/simotae14/vite-starter","last_synced_at":"2026-05-12T23:34:14.496Z","repository":{"id":217942848,"uuid":"745174339","full_name":"simotae14/vite-starter","owner":"simotae14","description":"Initial repo Vite course","archived":false,"fork":false,"pushed_at":"2025-12-22T22:21:23.000Z","size":5050,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-24T06:53:26.488Z","etag":null,"topics":["vite"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simotae14.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-18T19:35:30.000Z","updated_at":"2025-12-22T22:21:26.000Z","dependencies_parsed_at":"2024-01-18T22:18:02.598Z","dependency_job_id":"b65e4cb5-ccb9-4774-814e-a0203d1843b6","html_url":"https://github.com/simotae14/vite-starter","commit_stats":null,"previous_names":["simotae14/vite-starter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/simotae14/vite-starter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simotae14%2Fvite-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simotae14%2Fvite-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simotae14%2Fvite-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simotae14%2Fvite-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simotae14","download_url":"https://codeload.github.com/simotae14/vite-starter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simotae14%2Fvite-starter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32961785,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-12T23:30:32.555Z","status":"ssl_error","status_checked_at":"2026-05-12T23:30:18.191Z","response_time":102,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["vite"],"created_at":"2024-11-11T05:28:53.594Z","updated_at":"2026-05-12T23:34:14.481Z","avatar_url":"https://github.com/simotae14.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Getting Started with Vite\n\nIn this repository, we have a basic Vite setup in place. That is to say, we have Vite and an `index.html` file. Everything is mostly superfluous.\n\nWe can get the application started by running either of the following: `npm start` or `npx vite`.\n\nThis will start up a development server with a simple webpage.\n\n## Pulling in Some JavaScript\n\nAt first, adding a `\u003cscript\u003e` tag doesn't seem very exciting, but this is how Vite determines the initial entry point for our application.\n\nIn `src/index.js`, let's add the following:\n\n```js\nconsole.log('Hello World!');\n\ndocument.querySelector('h1').textContent = 'Hello World!';\n```\n\nIn `index.html`, we'll add a reference to this code:\n\n```html\n\u003cscript src=\"/src/index.js\"\u003e\u003c/script\u003e\n```\n\nThis will give us an error if we put it in the `\u003chead\u003e`, but we're going to ignore that error for a minute.\n\n## Importing Files\n\nIn `src/counter.js`, we have the logic for a simple little counter. Let's pull it into `src/index.js`.\n\n```js\nimport { initializeCounter } from './counter';\n\nconsole.log('Hello World!');\n\ndocument.querySelector('h1').textContent = 'Hello World!';\n\ninitializeCounter();\n```\n\nThis will blow up in a new and different way. You should see an error that looks something like this:\n\n\u003e index.js:1 Uncaught SyntaxError: Cannot use import statement outside a module\n\nLuckily, this is an easy fix.\n\n```html\n\u003cscript type=\"module\" src=\"/src/index.js\"\u003e\u003c/script\u003e\n```\n\nThis fixes both issues:\n\n1. Imports work as expected.\n2. The DOM is loaded by the time our script runs.\n\nYou can read more about `type=\"module\"` [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type).\n\n## Building\n\nYou can build the application using either:\n\n1. `npm run build`\n2. `npx vite build`\n\nThis will create a `dist` folder with the compiled output. The output will look something along these lines:\n\n```tree\ndist\n├── android-chrome-192x192.png\n├── android-chrome-512x512.png\n├── apple-touch-icon.png\n├── assets\n│   └── index-03e7ded5.js\n├── favicon-16x16.png\n├── favicon-32x32.png\n├── favicon.ico\n├── index.html\n├── logo192.png\n├── logo512.png\n├── manifest.json\n└── robots.txt\n```\n\nIt's everything in the `public` directory, our `index.html`, and the compiled bundle in an `assets` directory. In this case, it does some basic inlining and minification. There is nothing particularly special to see here.\n\n## Dynamic Imports\n\nIn the previous example, even through we've broken our code up between two modules, Rollup is smart enought to figure out that they're all loaded at the same time and inlines them.\n\nIf we used a `import()` to load our file dynamically, we'll see that it's smart enough to split up our code.\n\n```js\nimport('./counter.js').then(({ initializeCounter }) =\u003e {\n  initializeCounter();\n});\n```\n\nWe'll now see that we have two assets.\n\n```\ndist\n├── …\n├── assets\n│   ├── counter-7777d3c9.js\n│   └── index-1060a589.js\n└── …\n```\n\n### Hot Module Replacement\n\nOut of the box, Vite supports hot module replacement. This means that if you edit a file. Only that file will be replaced and the rest of the application will continue remain. This allows Vite to refresh the page quickly and maintain the state between reloads.\n\nMost of the time, when we're using a framework, we don't have to think about it and we'll get this for free. But, if we're doing something that has side effects, we may want to clean up after ourselves.\n\n`initializeCounter()` returns a function that removes its event listeners. In the code below, we're going to:\n\n1. Dynamically load `src/counter.js`\n2. Call `initialzeCounter()` and store its `cleanup` function.\n3. If the module is replaced using hot module reloading, we'll clean up the event listeners from the old one and then reinitialize the counter.\n\n```js\nimport('./counter.js').then(({ initializeCounter }) =\u003e {\n  const cleanup = initializeCounter();\n\n  if (import.meta.hot) {\n    import.meta.hot.accept(({ module }) =\u003e {\n      cleanup();\n      cleanup = module.initializeCounter();\n    });\n  }\n});\n```\n\nIf this code seems like a lot, keep in mind two things:\n\n1. This will be stripped out of the final build.\n2. Most frameworks will do this for you under the hood. This might be the most that you ever have to think about it.\n\n## Exercise: Dynamic Loading\n\nThis is a little bit contrived, but we're going to work with what we have. If the count goes negative, we want to show a banner.\n\nWe'll probably start with something like this:\n\n```js\nconst render = () =\u003e {\n  countElement.textContent = count;\n\n  if (count \u003c 0) {\n    // Your code here.\n  }\n};\n```\n\n\u003cdetails\u003e\u003csummary\u003eSolution\u003c/summary\u003e\n\n```js\nconst render = () =\u003e {\n  countElement.textContent = count;\n\n  if (count \u003c 0) {\n    import('./add-banner.js').then(({ addBanner }) =\u003e {\n      addBanner('The counter is negative!');\n    });\n  }\n};\n```\n\n\u003c/details\u003e\n\n## Adding CSS\n\nVite gives a few different ways to add CSS.\n\n1. We can add `\u003clink\u003e` tags as we've done for years.\n2. We can import the CSS files from our JavaScript.\n3. We can use CSS Modules.\n\n### Using a `\u003clink\u003e` tag\n\nLet's start with the most boring, but straight forward of the bunch. Add the following to your HTML.\n\n```html\n\u003clink rel=\"stylesheet\" href=\"/src/style.css\" /\u003e\n```\n\n### Importing a Stylesheet\n\nIn `counter.js`, we can import a stylesheet.\n\n```js\nimport './counter.css';\n```\n\nIn both cases, the CSS is loaded globally. The notable difference here is that this CSS file will only be loaded when this module is loaded.\n\n## Using CSS Modules\n\nIf you look closely, you'll notice that this CSS is _not_ rendering.\n\n```css\n.count {\n  font-size: 4em;\n  color: rebeccapurple;\n}\n```\n\nThis makes sense, because because we don't have anything with that class.\n\nIf we give a CSS file a `*.module.css` extension, then we can access its fingerprinted classes.\n\n```js\nimport styles from './counter.module.css';\n\n// …\n\ncountElement.classList.add(styles.count);\n```\n\nThis is the resulting class name.\n\n```html\n\u003cp id=\"count\" class=\"_count_1o9rn_1\"\u003e4\u003c/p\u003e\n```\n\n### Exercise: Add Banner\n\n- Can you add an additional script that shows a banner or an alert when the count gets below zero?\n- Can you use `banner.module.css` as a CSS module?\n\n\u003cdetails\u003e\u003csummary\u003eSolution\u003c/details\u003e\n\n```js\nimport styles from './banner.module.css';\n\n// …\n\nbanner.classList.add(styles.banner);\ncloseButton.classList.add(styles.button);\n```\n\n\u003c/details\u003e\n\nNotice how the CSS file is also dynamically added to the DOM as needed.\n\n## Using SCSS or Sass\n\nUsing SCSS (or Sass) is relatively straight-forward. Consider this change to our CSS.\n\n```scss\n.button {\n  padding: 0.5rem 1rem;\n  background-color: transparent;\n  border: none;\n  font-size: 20px;\n  cursor: pointer;\n  \u0026:hover {\n    background-color: rgba(255, 255, 255, 0.5);\n  }\n}\n```\n\nWe _could_ change the import to `./banner.module.scss`, but you'll see we get a _very_ easy to resolve error.\n\n\u003e Preprocessor dependency \"sass\" not found. Did you install it? Try `npm install -D sass`.\n\nWell, I guess we can handle this. That's it. Everything works as expected.\n\n## Using TypeScript\n\nOkay, but let's say you wanted to use TypeScript. That's probably a lot of set up, right?\n\nJust change the file extension to `.ts`. That's it.\n\n## Using TypeScript with CSS Modules\n\nWith a few minor changes, `add-banner.ts` works as expected. But, TypeScript is annoyed by the CSS module and the fact that it doesn't know it's type.\n\nWe're going to solve for this by using a little library called `typed-css-modules`.\n\n```sh\nnpm install -D typed-css-modules\n```\n\nNext, we can run `tcm src` and it will generate a `.d.ts` file for each CSS file.\n\nIf you want to keep this running, you can do something like this in your `package.json`.\n\n```json\n{\n  \"scripts\": {\n    \"watch\": \"vite \u0026 tcm --watch src\",\n    \"check:css\": \"tcm --listDifferent src\"\n  }\n}\n```\n\nOr, if you use husky, you can automate this whenever you commit a change to a CSS file. In `.husky/pre-commit`:\n\n```sh\n#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpm run check:css\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimotae14%2Fvite-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimotae14%2Fvite-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimotae14%2Fvite-starter/lists"}