Migrating WiniLogis from Webpack to Vite
While working on the WiniLogis project, I noticed that, compared with the company's other Vite-based projects, the dev environment was significantly slow, taking 39 seconds to start.
In particular, every code change made the browser re-render the whole page and show a white screen, and inefficiencies like this repeatedly broke the development flow.
The Jenkins pipeline also had long build times, which made the feedback loop from applying a code change to a finished deployment excessively long.
To clear these bottlenecks and improve the developer experience, I carried out a Webpack → Vite migration on the WiniLogis project. Below is how it went and what the results were.
Why I chose Vite
1. Overwhelmingly fast startup built on Native ESM
Webpack has to bundle the entire project when it starts, but Vite uses the browser's Native ESM to serve the pages you need right away, without bundling. It also pre-bundles external dependencies, which cuts dev server startup time dramatically.
2. Performance optimization by combining esbuild and Rollup
In development it uses esbuild, which is written in Go and is overwhelmingly fast, and for production builds it uses the stable Rollup. This let me speed up local development and also cut build time in the CI/CD pipeline.

3. Aligning the dev environment with the company's next-generation projects
All of the next-generation projects currently in progress at Autowini are built on Vite. By migrating the WiniLogis build system to match, I wanted to reduce the differences in dev environments between projects and maximize maintenance efficiency within the team.
Main migration steps
1. Installing packages and creating the config file
- Compiler optimization: Instead of the Babel-based plugin, I installed the Rust-based @vitejs/plugin-react-swc. This pushed HMR speed on the dev server and code transformation speed in production builds as high as possible.
- vite.config.ts: The old Webpack config had no complex logic beyond setting the output directory to build, so moving to Vite was very easy. I put the plugins, the path alias (src), and the dev server settings together in this one file to make them easier to manage.
- Adding type definitions: I created src/vite-env.d.ts and added type declarations for ImportMetaEnv, so environment variables are type-safe when used.
2. Moving and editing index.html
Unlike Webpack, which uses public/index.html as a template, Vite uses the index.html at the project root as its entry point, so I handled it as follows.
- Move to the root: I moved public/index.html to the top level of the project (root).
- Add the module entry: I inserted <script type="module" src="/src/index.tsx"></script> inside the <body> tag so that Vite recognizes the application code and can load the script as Native ESM.
3. Reorganizing the environment variable files
- Renaming files: In Vite, the .env.local file we had used with Webpack is a special file that is loaded in every mode. Keeping it as is could cause conflicts between per-environment settings, so I replaced it with .env.development, which is only for local development.
- Per-environment mapping: I created a new .env.staging for test deployments and, along with .env.production for production, assigned each environment its own VITE_MODE value.
4. Bulk replacement in the source code (with Claude Code)
Just as described in AB180's tech blog, which I read before the migration, problems came up in how environment variables were referenced.
I solved this with Claude Code.
- Using Claude Code, I converted 177 process.env references in roughly 50 or more files to import.meta.env.
- Syntax conversion: I changed process.env.NODE_ENV === 'production' to import.meta.env.PROD, a built-in Vite variable.
- Multi-line patterns: Because of Prettier's line-break rules, some code was split as process.env\n .VARIABLE, and a plain sed command can't replace that. Following Claude Code's suggestion, I used perl's -0777 option to read each whole file as a single string and replaced these exception patterns in bulk.
5. Changing package.json scripts and removing dependencies
With the build tool replaced, I optimized the run scripts and cleaned up unneeded packages to make the project lighter.
- Updating scripts: I changed the local run (start), test build (build:dev), and production build (build:prod) commands to use the Vite CLI. To stay compatible with the existing Jenkins pipeline, I kept the command names the same.
- Lighter dependencies: I removed 18 devDependencies that had been used for bundling, including webpack, babel-loader, css-loader, and dotenv-webpack. This reduced the size of node_modules and made dependencies easier to manage.
6. Handling the CI/CD pipeline and troubleshooting

After the migration, running the Jenkins pipeline produced a build error, so I updated the server environment to fix it.
- Upgrading Node.js: The Jenkins server was running Node.js v18.18.2, which did not meet the requirements of the latest Vite and its related dependencies, so the build failed. I updated the server's Node.js to v25 to fix the compatibility issue.
- Keeping the build output path: The existing Jenkins pipeline pointed at the build/ folder, so I kept vite.config.ts set to use build instead of dist, Vite's default output directory. That way deployment worked without changing the pipeline.
Migration results
1. Dev server startup: 39s → 148ms Because Vite loads only the files it needs right away instead of bundling the whole project, startup time dropped by a factor of about 260.
2. Project build: 29.09s → 4.43s With Vite's optimized build process, the time to bundle the source code dropped by about 85%. This minimized the waiting time during local work.
3. CI/CD pipeline time: 3m 30s → 1m 30s The faster build carried over to the Jenkins pipeline and cut the total deployment time by about 2 minutes. As a result, the feedback loop from code push to finished deployment became 2.3 times faster than before.
Looking back
A year ago, when my senior teammate migrated the WiniLogis admin project, I watched the process from beside them and thought a lot about where I would start if I someday improved the WiniLogis web project myself.
Now, as a third-year developer, I led this migration to improve the local dev environment and pipeline build times, and found a starting point for that question. The process went much more smoothly than I had vaguely feared, and it reminded me once again that "rather than spending time deliberating, the answer is to take it on directly."

After finishing the work, I looked at the 2025 State of JS and saw that Vite was ranked the most loved library. That also gave me confidence that this migration was the right choice.
WiniLogis currently uses a Bitbucket repository but deploys through Jenkins. I think management is more efficient when the repository and the CI/CD pipeline are integrated. Other projects at the company already run stably with that kind of integrated setup, so I plan to move WiniLogis to Bitbucket Pipelines soon as well and unify the operating environment.
- #Claude Code
- #Vite
- #webpack
- #WiniLogis
- #migration