Frontend Tips: Boost Productivity With This Vite Technique

·

Vite is the best and blazing fast frontend build tool. It includes all feature for developer to build web application faster, like HMR (Hot Module Replacement), build tools, plugins and build on top Rollup.

I was using this tool for a couple years, but I just found some tips to increase productivity. It’s a small change but as developer found

Jump to any where you want.

Let’s start from environment modes, it have opportunity to create hidden feature in development mode. Here is some idea you can add in your environment modes

Using ENV Modes to Change Appearance

When we create application, we confused by which tab browser shown development and production website, they have similar icon and title. Other developer separate the stage too. This could be difficult if we have 100 openned tabs.

So, I have idea. What if we change favicon based of environment? you got it right?

ENV and modes is built in variable generated when vite server running, but it will embed into script in building process. We can take advantage of this to switch appearance including favicon, title, component, etc. I will use vite plugin to subtitute the favicon. For example your favicon named favicon.png, and dev favicon is favicon-dev.png.

export default defineConfig({
  plugins: [
    {
      name: 'Change favicon icon Dev',
      transformIndexHtml(html) {
        const env = process.env.NODE_ENV || 'development';
        if(env !== 'development) return html;
        
        return html.replace("favicon.png", "favicon-dev.png");
      }
    }
  ]
})

Your website will looks different based of environment of application. transformIndexHtml can be used more than this, you can change title, minify it, change behaviour, etc. it’s useful function to modify html.

We will the same method to add banner to html

Tag Build using Banner

Frontend developer usually does not touch deployment process, small change in application are not visible. We have to add some tag build as versioning to match with our local development version.

Here me out: Let’s build small banner as application unique version! So I’ll know the production code is the latest code.

It doesn’t have to use semver (or better if you use that), using only timestamp build and git hash is sufficient. We will use the same method to create banner build, I will add version, env, last commit and timestamp build after tag <head>

const version = process.env.npm_package_version || '0.0.0';
const env = process.env.NODE_ENV || 'development';
const cmdLastcommit = 'git rev-parse --short HEAD';
const lastCommit = childProcess.execSync(cmdLastcommit).toString().trim();


export default defineConfig({
  plugins: [
    {
      name: 'Add Banner HTML',
      transformIndexHtml(html) {
        const banner = `My app ${version} — ${env} — ${lastCommit} — built on ${new Date().toISOString()}`;
        
        return html.replace(
          '<head>',
          `<head>\n <!-- ${banner} -->`
        );
      }
    }
  ]
})

The result will looks like this when you build the application. Press ctrl + u or cmd + u to see the source code.

<!DOCTYPE html>
<html lang="en">
  <head>
 <!-- My app 1.0.8-beta-2025.8.22-1 — production — 985c46d — built on 2025-08-29T08:14:08.920Z -->
    <meta charset="UTF-8" />

Here is some benefit if you do this:

  • You know the build file is correct
  • DevOps team are able validate their deployment
  • Monitor the caching system and flush the cache if necessary.

it’s very useful when we push the code and validate deployed version with our version before doing everything. Just to make sure everything run as expected. No more fight with DevOps team.

Another Hidden feature in Development Mode

Here is my favorite, if you are using CSR (Client side rendering) framework like ReactJS or VueJS, you can create a component to appears only in development mode but not in build file nor on production. Here is my example using JSX Code, it’s return empty on non-development.

function Debug({data}: {data:any}){
  if(import.meta.env.DEV === false) return <></>
  
  return (<div>{JSON.stringify(data, null, 2)}</div>)
}

This will create a debug view only on development mode. Here is some useful example cases:

  • Show corresponding component response from API without checking network log.
  • Show selected value for ton of fields.
  • Show action development, for example copy to clipboard of token, do refresh token.

Here is my actual example, left image is developer tool to copy token—my backend are using JWT Token—, action to refresh token and open documentation API. It’s handy to click it as I want to check anything as expected since integrating to RESTFul API.

On the other hand, right image shown red box. It’s a debug ID of items, because my client does not want it. So, I built this to make sure everything is in correct order.

Here is my complete debug component in ReactJS, also I add some cheat code to toggle the state debug mode.

import { cn } from '@/lib/utils';
import { Slot } from '@radix-ui/react-slot';
import React from 'react';
import { create, useStore } from 'zustand';

interface DebugModeState {
  isDebugMode: boolean;
}

const useDebugModeStore = create<DebugModeState>()((set) => ({
  isDebugMode: import.meta.env.DEV,
  setDebugMode: (isDebugMode: boolean) => set({ isDebugMode }),
}))

window.addEventListener('keydown', (e) => {
  const ENV_DEV = import.meta.env.DEV;
  if (!ENV_DEV) return;
  if (e.key === 'd' && e.ctrlKey) {
    const isDebugMode = useDebugModeStore.getState().isDebugMode;
    useDebugModeStore.setState({ isDebugMode: !isDebugMode });
  }
})

type Props = { asChild?: boolean }

const DebugMode = React.forwardRef<
  HTMLDivElement,
  React.ComponentProps<"div"> & Props
>(({ className, asChild = false, ...props }, ref) => {
  const Comp = asChild ? Slot : "div"

  const isDebugMode = useStore(useDebugModeStore, (state) => state.isDebugMode);

  if (isDebugMode == false || !props.children) {
    return null;
  }

  return (
    <Comp
      ref={ref}
      className={cn(className, 'outline outline-red-500 debug-mode text-muted-foreground bg-muted hover:text-black')}
      {...props}
    ></Comp>
  )
});

export {
  DebugMode
};
Expand

I found this is extremely useful, because I can validate input, output, REST API Response, state, toggle features, A/B testing, etc. Maybe you can add more hidden feature like “click some part couple times to open dev mode”. Just like how android, windows, macos hide their labs feature.

Leverage Multi-pages Feature

Vite start its debut for SPA and CSR developer that only use single html to create their application. But, vite able ot use multiple html as entry point. How to leverage this feature?

Imagine this, your application have feature: landing page, account page, application page, confirmation page. If we think-in-SPA, every page routed using routing js. it will single js as entry point become large.

Instead using single html, separate the page as html and each page have their own js file.

  • Landing page—Should load instantly, using plain html or template engine will make website lightweight.
  • Authentication page should load instantly, so write in html only with small js as interaction
  • Small pages—like OTP Input page, confirmation page, logout page, etc. It should load instantly and write in HTML.
  • Application page—imagine this as your full application, put CSR on this.

By doing this, your build code will become smaller, resulting in a lighter website load and the elimination of unnecessary processes.

- vite.config.js
- index.html
- about.html
- login.html
- forgot-password.html
- app.html
- src/ 
  - index.js
  - about.js
  - login.js
  - forgot-password.js
  - app.js              // CSR application
  
  - style.css
  
  app-pages/
    - routing.js
    - dashboard.js
    - other-page.js

As you can see, we start the project with some html pages as entry point, The src folder where JavaScript and TypeScript code will be stored. If you work with several teams of frontend, you can use different frameworks like ReactJS or VueJS, even though it’s not recommended way because you will get messy codes, but it’s possible.

Conclusion

Vite is the best building frontend tool, I read Vite documentation and code front and back to know how Vite works for increasing productivity, developer experience, less headache, and keeping the state of workflow.

I always found some trick and idea from browsing and community feedback, I hope this is useful for community and my self (in the future). Thank you for your reading, please press that subscribe button to get my latest post!