├── .eslintrc.cjs ├── .styleci.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── RELEASE.md ├── UPGRADE.md ├── bin └── clean.js ├── package.json ├── src ├── dev-server-index.html ├── index.ts └── inertia-helpers │ └── index.ts ├── tsconfig.inertia-helpers.json └── tsconfig.json /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | parser: "@typescript-eslint/parser", 7 | plugins: ["@typescript-eslint"], 8 | extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 9 | rules: { 10 | "no-trailing-spaces": "error", 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | php: 2 | preset: laravel 3 | js: true 4 | css: true 5 | ts: true 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | ## [Unreleased](https://github.com/laravel/vite-plugin/compare/v1.3.0...1.x) 4 | 5 | ## [v1.3.0](https://github.com/laravel/vite-plugin/compare/v1.2.0...v1.3.0) - 2025-06-03 6 | 7 | * Use rollup types from Vite by [@sapphi-red](https://github.com/sapphi-red) in https://github.com/laravel/vite-plugin/pull/325 8 | 9 | ## [v1.2.0](https://github.com/laravel/vite-plugin/compare/v1.1.1...v1.2.0) - 2025-01-21 10 | 11 | * [1.x] Fix Invalid URL issue with Vite 6.0.9 by [@batinmustu](https://github.com/batinmustu) in https://github.com/laravel/vite-plugin/pull/317 12 | * [1.x] Add default CORS origins by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/318 13 | 14 | ## [v1.1.1](https://github.com/laravel/vite-plugin/compare/v1.1.0...v1.1.1) - 2024-12-03 15 | 16 | * [1.1] Fix dependency issue with Vite 5 by [@jessarcher](https://github.com/jessarcher) in https://github.com/laravel/vite-plugin/pull/313 17 | 18 | ## [v1.1.0](https://github.com/laravel/vite-plugin/compare/v1.0.6...v1.1.0) - 2024-12-02 19 | 20 | * Upgrade to Vite 6 by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/310 21 | 22 | ## [v1.0.6](https://github.com/laravel/vite-plugin/compare/v1.0.5...v1.0.6) - 2024-11-12 23 | 24 | * Replace dead link in Security Policy by [@Jubeki](https://github.com/Jubeki) in https://github.com/laravel/vite-plugin/pull/300 25 | * Look for certificates in valet linux config directory by [@jameshulse](https://github.com/jameshulse) in https://github.com/laravel/vite-plugin/pull/307 26 | 27 | ## [v1.0.5](https://github.com/laravel/vite-plugin/compare/v1.0.4...v1.0.5) - 2024-07-09 28 | 29 | * TypeScript: define entrypoints using object by [@tylerlwsmith](https://github.com/tylerlwsmith) in https://github.com/laravel/vite-plugin/pull/298 30 | 31 | ## [v1.0.4](https://github.com/laravel/vite-plugin/compare/v1.0.3...v1.0.4) - 2024-05-17 32 | 33 | * Include base in hotFile without modifying server.origin replacement by [@danielztolnai](https://github.com/danielztolnai) in https://github.com/laravel/vite-plugin/pull/296 34 | 35 | ## [v1.0.3](https://github.com/laravel/vite-plugin/compare/v1.0.2...v1.0.3) - 2024-05-16 36 | 37 | * Append base to hot file by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/290 38 | * Support Laravel Herd for windows by [@mozex](https://github.com/mozex) in https://github.com/laravel/vite-plugin/pull/293 39 | 40 | ## [v1.0.2](https://github.com/laravel/vite-plugin/compare/v1.0.1...v1.0.2) - 2024-02-28 41 | 42 | * [1.x] Fix HMR issue when `resources/lang` directory doesn't exist and a symlink is present in the root directory by [@jessarcher](https://github.com/jessarcher) in https://github.com/laravel/vite-plugin/pull/285 43 | 44 | ## [v1.0.1](https://github.com/laravel/vite-plugin/compare/v1.0.0...v1.0.1) - 2023-12-27 45 | 46 | * [1.x] Simpler conditional by [@Jubeki](https://github.com/Jubeki) in https://github.com/laravel/vite-plugin/pull/273 47 | * [1.x] Account for imported CSS files while cleaning by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/275 48 | * [1.x] Fix exit error messages by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/276 49 | 50 | ## [v1.0.0](https://github.com/laravel/vite-plugin/compare/v0.8.1...v1.0.0) - 2023-12-19 51 | 52 | * [1.0] Drop CJS build and export types first by [@benmccann](https://github.com/benmccann) in https://github.com/laravel/vite-plugin/pull/235 53 | * [1.x] Introduce `clean-orphaned-assets` binary by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/251 54 | * [0.8.x] Respect vite server.origin in viteDevServerUrl by [@nurdism](https://github.com/nurdism) in https://github.com/laravel/vite-plugin/pull/255 55 | * [1.x] Vite 5 by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/269 56 | * [0.8.x] Fallback pages by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/271 57 | * [1.x] Auto detect Valet / Herd TLS certificates by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/180 58 | 59 | ## [v0.8.1](https://github.com/laravel/vite-plugin/compare/v0.8.0...v0.8.1) - 2023-09-26 60 | 61 | - [0.8] Fix issue with `0.0.0.0` network resolution by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/vite-plugin/pull/241 62 | - Upgrade vitest by [@sapphi-red](https://github.com/sapphi-red) in https://github.com/laravel/vite-plugin/pull/246 63 | 64 | ## [v0.8.0](https://github.com/laravel/vite-plugin/compare/v0.7.8...v0.8.0) - 2023-08-08 65 | 66 | - fix: compile error following upgrade.md's vite to mix guide by [@AshboDev](https://github.com/AshboDev) in https://github.com/laravel/vite-plugin/pull/231 67 | - Support Laravel Herd by [@claudiodekker](https://github.com/claudiodekker) in https://github.com/laravel/vite-plugin/pull/233 68 | 69 | ## [v0.7.8](https://github.com/laravel/vite-plugin/compare/v0.7.7...v0.7.8) - 2023-05-24 70 | 71 | - Ensure 'node' has a fallback type when working with static import linters by @timacdonald in https://github.com/laravel/vite-plugin/pull/227 72 | 73 | ## [v0.7.7](https://github.com/laravel/vite-plugin/compare/v0.7.6...v0.7.7) - 2023-05-16 74 | 75 | - Expose base types by @timacdonald in https://github.com/laravel/vite-plugin/pull/220 76 | - Add a DOCTYPE by @matijs in https://github.com/laravel/vite-plugin/pull/215 77 | 78 | ## [v0.7.6](https://github.com/laravel/vite-plugin/compare/v0.7.5...v0.7.6) - 2023-05-10 79 | 80 | - Polyfill import.meta.url for CJS builds by @timacdonald in https://github.com/laravel/vite-plugin/pull/217 81 | 82 | ## [v0.7.5](https://github.com/laravel/vite-plugin/compare/v0.7.4...v0.7.5) - 2023-05-09 83 | 84 | - Build MJS and CJS versions of the plugin by @timacdonald in https://github.com/laravel/vite-plugin/pull/189 85 | 86 | ## [v0.7.4](https://github.com/laravel/vite-plugin/compare/v0.7.3...v0.7.4) - 2023-02-07 87 | 88 | ### Added 89 | 90 | - Provide hook to access dev url while transforming by @timacdonald in https://github.com/laravel/vite-plugin/pull/195 91 | 92 | ## [v0.7.3](https://github.com/laravel/vite-plugin/compare/v0.7.2...v0.7.3) - 2022-12-20 93 | 94 | ### Changed 95 | 96 | - Update package.json to use vite 4 compatible vite-plugin-full-reload by @iquad in https://github.com/laravel/vite-plugin/pull/186 97 | - Respects users base config option by @timacdonald in https://github.com/laravel/vite-plugin/pull/188 98 | 99 | ## [v0.7.2](https://github.com/laravel/vite-plugin/compare/v0.7.1...v0.7.2) - 2022-12-15 100 | 101 | ### Added 102 | 103 | - Adds Vite 4 support in https://github.com/laravel/vite-plugin/pull/179 104 | 105 | ## [v0.7.1](https://github.com/laravel/vite-plugin/compare/v0.7.0...v0.7.1) - 2022-11-21 106 | 107 | ### Fixed 108 | 109 | - Fix node type issue by @timacdonald in https://github.com/laravel/vite-plugin/pull/166 110 | 111 | ## [v0.7.0](https://github.com/laravel/vite-plugin/compare/v0.6.1...v0.7.0) - 2022-10-25 112 | 113 | ### Changed 114 | 115 | - Respect user manifest config by @jessarcher in https://github.com/laravel/vite-plugin/pull/150 116 | - Support loading certificates from environment variables by @innocenzi in https://github.com/laravel/vite-plugin/pull/151 117 | 118 | ### Fixed 119 | 120 | - Fix colors by @timacdonald in https://github.com/laravel/vite-plugin/pull/154 121 | 122 | ## [v0.6.1](https://github.com/laravel/vite-plugin/compare/v0.6.0...v0.6.1) - 2022-09-21 123 | 124 | ### Changed 125 | 126 | - Fail running HMR in known environments by @timacdonald in https://github.com/laravel/vite-plugin/pull/128 127 | - Do not inline small assets, by default by @timacdonald in https://github.com/laravel/vite-plugin/pull/131 128 | - Add `lang` directories to default refresh paths by @fabio-ivona in https://github.com/laravel/vite-plugin/pull/135 129 | - Add config option to utilise Valet TLS certificates by @timacdonald in https://github.com/laravel/vite-plugin/pull/129 130 | 131 | ### Fixed 132 | 133 | - Ensure custom 404 page shows after server restarts by @timacdonald in https://github.com/laravel/vite-plugin/pull/141 134 | 135 | ## [v0.6.0](https://github.com/laravel/vite-plugin/compare/v0.5.4...v0.6.0) - 2022-08-25 136 | 137 | ### Added 138 | 139 | - Support customising hot file / build path by @timacdonald in https://github.com/laravel/vite-plugin/pull/118 140 | 141 | ## [v0.5.4](https://github.com/laravel/vite-plugin/compare/v0.5.3...v0.5.4) - 2022-08-16 142 | 143 | ### Changed 144 | 145 | - Allow chosing different env files by @LucdoOf in https://github.com/laravel/vite-plugin/pull/113 146 | 147 | ## [v0.5.3](https://github.com/laravel/vite-plugin/compare/v0.5.2...v0.5.3) - 2022-08-04 148 | 149 | ### Fixed 150 | 151 | - Support both string and integer based IP versions by @timacdonald in https://github.com/laravel/vite-plugin/pull/108 152 | 153 | ## [v0.5.2](https://github.com/laravel/vite-plugin/compare/v0.5.1...v0.5.2) - 2022-07-22 154 | 155 | No major changes. 156 | 157 | ## [v0.5.1](https://github.com/laravel/vite-plugin/compare/v0.5.0...v0.5.1) - 2022-07-22 158 | 159 | ### Fixed 160 | 161 | - Do not externalise inertia helpers by @timacdonald in https://github.com/laravel/vite-plugin/pull/95 162 | - Prevent console warning when Vite pings HMR by @jessarcher in https://github.com/laravel/vite-plugin/pull/98 163 | - Use HMR port when specified by @guilheb in https://github.com/laravel/vite-plugin/pull/63 164 | 165 | ## [v0.5.0](https://github.com/laravel/vite-plugin/compare/v0.4.0...v0.5.0) - 2022-07-19 166 | 167 | ### Added 168 | 169 | - Vite 3 support by @timacdonald in https://github.com/laravel/vite-plugin/pull/77 170 | 171 | ## [v0.4.0](https://github.com/laravel/package-template/compare/v0.1.0...v0.4.0) - 2022-07-13 172 | 173 | ### Changed 174 | 175 | - Help users that visit the Vite dev server directly by @jessarcher in https://github.com/laravel/vite-plugin/pull/57 176 | - Change default SSR build directory by @jessarcher in https://github.com/laravel/vite-plugin/pull/70 177 | 178 | ## v0.1.0 (2022-05-28) 179 | 180 | Initial pre-release. 181 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Taylor Otwell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Vite Plugin 2 | 3 | Build Status 4 | Total Downloads 5 | Latest Stable Version 6 | License 7 | 8 | ## Introduction 9 | 10 | [Vite](https://vitejs.dev) is a modern frontend build tool that provides an extremely fast development environment and bundles your code for production. 11 | 12 | This plugin configures Vite for use with a Laravel backend server. 13 | 14 | ## Official Documentation 15 | 16 | Documentation for the Laravel Vite plugin can be found on the [Laravel website](https://laravel.com/docs/vite). 17 | 18 | ## Contributing 19 | 20 | Thank you for considering contributing to the Laravel Vite plugin! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). 21 | 22 | ## Code of Conduct 23 | 24 | In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). 25 | 26 | ## Security Vulnerabilities 27 | 28 | Please review [our security policy](https://github.com/laravel/vite-plugin/security/policy) on how to report security vulnerabilities. 29 | 30 | ## License 31 | 32 | The Laravel Vite plugin is open-sourced software licensed under the [MIT license](LICENSE.md). 33 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Instructions 2 | 3 | Releases are managed by [@taylorotwell](https://github.com/taylorotwell), [@jessarcher](https://github.com/jessarcher), and [@timacdonald](https://github.com/timacdonald) for this repository. 4 | 5 | 1. Update the version number in [package.json](./package.json) and commit it 6 | 2. `rm -rf node_modules package-lock.json` 7 | 3. `npm install` 8 | 4. `npm run build` 9 | 5. `npm publish` 10 | 6. Create a new GitHub release for this version with the release notes 11 | -------------------------------------------------------------------------------- /UPGRADE.md: -------------------------------------------------------------------------------- 1 | # Upgrade Guide 2 | 3 | ## `0.x` to `1.x` 4 | 5 | - Adds support for Vite 5 and removes support for Vite 3 and 4. 6 | - Introduces an `npx clean-orphaned-assets` command to clean orphaned assets in Vite's build directories. 7 | - Introduces Valet / Herd TLS certificate auto detection. 8 | - Adds `app/Livewire/**` to the default "refresh" paths. 9 | - Adds output of SSR manifest for SSR builds. 10 | 11 | ### Notable Changes 12 | 13 | 1. Dropped CJS build: https://github.com/laravel/vite-plugin/pull/235 14 | 2. Dropped support for a `boolean` value of `server.https` option in `vite.config.js`: https://github.com/laravel/vite-plugin/pull/254 15 | 3. Dropped support for Node 14, 15, 16, 17, and 19: https://github.com/laravel/vite-plugin/pull/269 16 | 17 | Please see the [Vite migration documentation](https://vitejs.dev/guide/migration) for why these changes have been made and additional changes you may need to consider. 18 | 19 | ### Upgrade Path 20 | 21 | 1. Update to the latest version of the `laravel-vite-plugin`, `vite`, and any Vite plugins you may have installed, such as [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue) which requires version `^4.5.0` or [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react) which requires version `^4.2.0` to be compatible with Vite 5. 22 | 23 | The following command will update `laravel-vite-plugin` and `vite` only. You may need to include any additional plugin updates as needed by your application: 24 | 25 | ``` 26 | npm install --save-dev vite@^5.0.0 laravel-vite-plugin@^1.0.0 27 | ``` 28 | 29 | You should also check the upgrade guide and changelogs for any packages you update, including [Vite's migrations guide](https://vitejs.dev/guide/migration.html). 30 | 31 | 2. Ensure your `package.json` contains `"type": "module"`. 32 | 33 | Run the following command in your project's root directory or anywhere you have your `package.json` files: 34 | 35 | ```sh 36 | npm pkg set type=module 37 | ``` 38 | 39 | You may also need to rename any `*.js` configuration files that contain CJS, which is the older-style Node-flavored `var plugin = require('plugin')` syntax, to `filename.cjs` after making this change. 40 | 41 | ## Migrating from Laravel Mix to Vite 42 | 43 | > **Note** 44 | > This upgrade guide does not cover all possible Mix use cases, such as Sass compilation. Please consult the [Vite documentation](https://vitejs.dev/guide/) for information on configuring Vite for these scenarios. 45 | 46 | ### Update Laravel Framework 47 | 48 | To make use of the new Vite integration, you will need to update to at least version `9.19.0` of the `laravel/framework`: 49 | 50 | ```sh 51 | composer require laravel/framework:^9.19.0 52 | ``` 53 | 54 | ### Install Vite and the Laravel Plugin 55 | 56 | First, you will need to install [Vite](https://vitejs.dev/) and the [Laravel Vite Plugin](https://www.npmjs.com/package/laravel-vite-plugin) using your npm package manager of choice: 57 | 58 | ```shell 59 | npm install --save-dev vite laravel-vite-plugin 60 | ``` 61 | 62 | You may also need to install additional Vite plugins for your project, such as the Vue or React plugins: 63 | 64 | ```shell 65 | npm install --save-dev @vitejs/plugin-vue 66 | ``` 67 | 68 | ```shell 69 | npm install --save-dev @vitejs/plugin-react 70 | ``` 71 | 72 | ### Configure Vite 73 | 74 | Create a `vite.config.js` file in the root of your project: 75 | 76 | ```js 77 | import { defineConfig } from 'vite'; 78 | import laravel from 'laravel-vite-plugin'; 79 | // import react from '@vitejs/plugin-react'; 80 | // import vue from '@vitejs/plugin-vue'; 81 | 82 | export default defineConfig({ 83 | plugins: [ 84 | laravel([ 85 | 'resources/css/app.css', 86 | 'resources/js/app.js', 87 | ]), 88 | // react(), 89 | // vue({ 90 | // template: { 91 | // transformAssetUrls: { 92 | // base: null, 93 | // includeAbsolute: false, 94 | // }, 95 | // }, 96 | // }), 97 | ], 98 | }); 99 | ``` 100 | 101 | If you are building an SPA, you will get a better developer experience by removing the CSS entry point above and [importing your CSS from Javascript](#importing-your-css-from-your-javascript-entry-points). 102 | 103 | #### Update Aliases 104 | 105 | If you are migrating aliases from your `webpack.mix.js` file to your `vite.config.js` file, you should ensure that the paths start with `/`. For example, `resources/js` would become `/resources/js`: 106 | 107 | ```js 108 | export default defineConfig({ 109 | plugins: [ 110 | laravel([ 111 | 'resources/css/app.css', 112 | 'resources/js/app.js', 113 | ]), 114 | ], 115 | resolve: { 116 | alias: { 117 | '@': '/resources/js' 118 | } 119 | } 120 | }); 121 | ``` 122 | 123 | For your convenience, the Laravel Vite plugin automatically adds an `@` alias for your `/resources/js` directory. If you do not need to customize your aliases, you may omit this section from your `vite.config.js` file. 124 | 125 | ### Update NPM scripts 126 | 127 | Update your NPM scripts in `package.json`: 128 | 129 | ```diff 130 | "scripts": { 131 | - "dev": "npm run development", 132 | - "development": "mix", 133 | - "watch": "mix watch", 134 | - "watch-poll": "mix watch -- --watch-options-poll=1000", 135 | - "hot": "mix watch --hot", 136 | - "prod": "npm run production", 137 | - "production": "mix --production" 138 | + "dev": "vite", 139 | + "build": "vite build" 140 | } 141 | ``` 142 | 143 | You should also add `"type": "module"` as a top-level key / value pair to your project's `package.json` by running the following command: 144 | 145 | ```shell 146 | npm pkg set type="module" 147 | ``` 148 | 149 | ### Vite compatible imports 150 | 151 | Vite only supports ES modules, so if you are upgrading an existing application you will need to replace any `require()` statements with `import`. You may refer to [this pull request](https://github.com/laravel/laravel/pull/5895/files) for an example. 152 | 153 | #### Inertia 154 | 155 | Inertia makes use of a `require()` call that is more complex to replicate with Vite. 156 | 157 | The following function can be used instead: 158 | 159 | ```diff 160 | + import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; 161 | 162 | createInertiaApp({ 163 | title: (title) => `${title} - ${appName}`, 164 | - resolve: (name) => require(`./Pages/${name}.vue`), 165 | + resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')), 166 | setup({ el, app, props, plugin }) { 167 | return createApp({ render: () => h(app, props) }) 168 | .use(plugin) 169 | .mixin({ methods: { route } }) 170 | .mount(el); 171 | }, 172 | }); 173 | ``` 174 | 175 | Additionally, you should ensure you have updated to at least version `0.6.3` of the `inertia-laravel` package: 176 | 177 | ```sh 178 | composer require inertiajs/inertia-laravel:^0.6.3 179 | ``` 180 | 181 | ### Update environment variables 182 | 183 | You will need to update the environment variables that are explicitly exposed in your `.env` files and in hosting environments such as Forge to use the `VITE_` prefix instead of `MIX_`: 184 | 185 | ```diff 186 | - MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 187 | - MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 188 | + VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 189 | + VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 190 | ``` 191 | 192 | > **Note** 193 | > You may optionally maintain the `MIX_` prefix by [configuring Vite](https://vitejs.dev/config/#envprefix) to use it. 194 | 195 | You will also need to update these references in your JavaScript code to use the new variable name and Vite syntax: 196 | 197 | ```diff 198 | - key: process.env.MIX_PUSHER_APP_KEY, 199 | - cluster: process.env.MIX_PUSHER_APP_CLUSTER, 200 | + key: import.meta.env.VITE_PUSHER_APP_KEY, 201 | + cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, 202 | ``` 203 | 204 | ### Importing your CSS from your JavaScript entry point(s) 205 | 206 | If you are building an SPA, you will get a better experience by importing your CSS from your JavaScript entry point(s), such as your `resources/js/app.js` entry point: 207 | 208 | ```diff 209 | import './bootstrap'; 210 | + import '../css/app.css'; 211 | ``` 212 | 213 | In development mode, Vite will automatically inject your CSS into the page. In production, a dedicated stylesheet will be generated that the `@vite` directive will load from the manifest. 214 | 215 | ### Replace `mix()` with `@vite` 216 | 217 | When using Vite, you will need to use the `@vite` Blade directive instead of the `mix()` helper. 218 | 219 | This will automatically detect whether you are running in serve or build mode and include all of the required ` 224 | + @vite(['resources/css/app.css', 'resources/js/app.js']) 225 | ``` 226 | 227 | The entry points should match those used in your `vite.config.js`. 228 | 229 | #### React 230 | 231 | If you are using React and hot-module replacement, you will need to include an additional directive *before* the `@vite` directive: 232 | 233 | ```html 234 | @viteReactRefresh 235 | @vite('resources/js/app.jsx') 236 | ``` 237 | 238 | This loads a React "refresh runtime" in development mode only, which is required for hot module replacement to work correctly. 239 | 240 | ### JavaScript files containing JSX must use a `.jsx` extension 241 | 242 | You will need to rename any `.js` files containing JSX to instead have a `.jsx` extension. If you need to rename your entry point then you should read the [entry point docs](https://laravel.com/docs/9.x/vite#configuring-vite) to learn how to configure the Laravel plugin for your project. 243 | 244 | See [this tweet](https://twitter.com/youyuxi/status/1362050255009816577) from Vite's creator for more information. 245 | 246 | > **Note** 247 | > If you are using Tailwind, remember to update the paths in your `tailwind.config.js` file. 248 | 249 | ### Vue imports must include the `.vue` extension 250 | 251 | ```diff 252 | - import Button from './Button'; 253 | + import Button from './Button.vue'; 254 | ``` 255 | 256 | ### Remove Laravel Mix 257 | 258 | The Laravel Mix package can now be uninstalled: 259 | 260 | ```shell 261 | npm remove laravel-mix 262 | ``` 263 | 264 | And you may remove your Mix configuration file: 265 | 266 | ```shell 267 | rm webpack.mix.js 268 | ``` 269 | 270 | If you are using StyleCI and have ignored the `webpack.mix.js` file in your configuration, you may also wish to remove the ignore rule. 271 | 272 | ### Update Test Helpers 273 | 274 | If you are using the `$this->withoutMix();` helper in your tests, you should replace this with `$this->withoutVite()`: 275 | 276 | ```diff 277 | - $this->withoutMix(); 278 | + $this->withoutVite(); 279 | ``` 280 | 281 | ### Vapor 282 | 283 | If you are deploying your application to Laravel Vapor, there are a few things you will want to handle before deploying. 284 | 285 | Ensure you have updated to at least version `1.40.0` of the Vapor CLI package: 286 | 287 | ```sh 288 | composer require laravel/vapor-cli:^1.40.0 289 | ``` 290 | 291 | Next, if you are using the Vapor asset helper in your application, you only need to utilize the asset helper when you are referencing assets you don't want bundled, such as those that already live in your public directory. 292 | 293 | If you want to use the asset helper with your Vite project, you will also need to ensure you have updated to the latest version: 294 | 295 | 296 | ```sh 297 | npm install laravel-vapor@latest 298 | ``` 299 | 300 | Then you will need to specify the base URL for assets in your application's entry point, for example in your `resources/js/app.js,` like so: 301 | 302 | ```diff 303 | - window.Vapor = require('laravel-vapor'); 304 | + import Vapor from 'laravel-vapor'; 305 | 306 | + window.Vapor = Vapor; 307 | + window.Vapor.withBaseAssetUrl(import.meta.env.VITE_VAPOR_ASSET_URL) 308 | ``` 309 | 310 | ### Optional: Configure Tailwind 311 | 312 | If you are using Tailwind, perhaps with one of Laravel's starter kits, you will need to migrate your `tailwind.config.js` configuration file to use [Vite compatible imports](#vite-compatible-imports) and exports: 313 | 314 | ```diff 315 | - const defaultTheme = require('tailwindcss/defaultTheme'); 316 | + import defaultTheme from 'tailwindcss/defaultTheme'; 317 | + import forms from '@tailwindcss/forms'; 318 | 319 | /** @type {import('tailwindcss').Config} */ 320 | - module.exports = { 321 | + export default { 322 | content: [ 323 | './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php', 324 | './storage/framework/views/*.php', 325 | './resources/views/**/*.blade.php', 326 | './resources/js/**/*.vue', 327 | ], 328 | 329 | theme: { 330 | extend: { 331 | fontFamily: { 332 | sans: ['Figtree', ...defaultTheme.fontFamily.sans], 333 | }, 334 | }, 335 | }, 336 | 337 | - plugins: [require('@tailwindcss/forms')], 338 | + plugins: [forms], 339 | }; 340 | ``` 341 | 342 | You will also need to create a `postcss.config.cjs` file. Tailwind can generate this for you automatically: 343 | 344 | ```shell 345 | npx tailwindcss init -p 346 | ``` 347 | 348 | Or, you can create it manually: 349 | 350 | ```js 351 | export default { 352 | plugins: { 353 | tailwindcss: {}, 354 | autoprefixer: {}, 355 | }, 356 | } 357 | ``` 358 | 359 | If you are using other PostCSS plugins, such as `postcss-import`, you will need to include them in your configuration. 360 | 361 | ### Optional: Git ignore the build directory 362 | 363 | Vite will place all of your build assets into a `build` subdirectory inside your public directory. If you prefer to build your assets on deploy instead of committing them to your repository, you may wish to add this directory to your `.gitignore` file: 364 | 365 | ```gitignore 366 | /public/build 367 | ``` 368 | 369 | ### Optional: Update SSR configuration 370 | 371 | You may remove your dedicated Laravel Mix SSR configuration: 372 | 373 | ```shell 374 | rm webpack.ssr.mix.js 375 | ``` 376 | 377 | In most cases, you won't need a dedicated SSR configuration file when using Vite. You can specify your SSR entry point by passing a configuration option to the Laravel plugin: 378 | 379 | ```js 380 | import { defineConfig } from 'vite'; 381 | import laravel from 'laravel-vite-plugin'; 382 | 383 | export default defineConfig({ 384 | plugins: [ 385 | laravel({ 386 | input: 'resources/js/app.js', 387 | ssr: 'resources/js/ssr.js', 388 | }), 389 | ], 390 | }); 391 | ``` 392 | 393 | You may wish to add the following additional scripts to your `package.json`: 394 | 395 | ```diff 396 | "scripts": { 397 | "dev": "vite", 398 | - "build": "vite build" 399 | + "build": "vite build && vite build --ssr" 400 | } 401 | ``` 402 | 403 | If you prefer to build your assets on deploy instead of committing them to your repository, you may wish to add the SSR output directory to your `.gitignore` file: 404 | 405 | ```gitignore 406 | /bootstrap/ssr 407 | ``` 408 | 409 | You may start the SSR server using `node`: 410 | 411 | ```sh 412 | node bootstrap/ssr/ssr.mjs 413 | ``` 414 | 415 | ### Optional: Expose Vite port when using Laravel Sail 416 | 417 | If you would like to run the `npm run dev` command in a Laravel Sail container, you will need to publish a port in your `docker-compose.yml` file: 418 | 419 | ```diff 420 | ports: 421 | - '${APP_PORT:-80}:80' 422 | + - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' 423 | ``` 424 | 425 | ### Wrapping up 426 | 427 | You should now be able to build your assets using `dev` command. This will also invoke the Vite server and Vite will watch for file changes: 428 | 429 | ```shell 430 | npm run dev 431 | ``` 432 | 433 | Alternatively, if you need to build files without watching or if you need to build them for production, you may use the `build` command: 434 | 435 | ```shell 436 | npm run build 437 | ``` 438 | 439 | For further information on how to use Vite, please check out [the Laravel Vite documentation](https://laravel.com/docs/vite). 440 | 441 | ### Troubleshooting 442 | 443 | If you have followed the upgrade guide, but are still having issues you should try the following steps: 444 | 445 | - Run `php artisan view:clear` to clear any compiled view assets. 446 | - If your development web server is running on HTTPS, check out the ["Working With A Secure Development Server"](https://laravel.com/docs/9.x/vite#working-with-a-secure-development-server) section of the documentation. 447 | 448 | ## Migrating from Vite to Laravel Mix 449 | 450 | ### Install Laravel Mix 451 | 452 | First, you will need to install Laravel Mix using your npm package manager of choice: 453 | 454 | ```shell 455 | npm install --save-dev laravel-mix 456 | ``` 457 | 458 | ### Configure Mix 459 | 460 | Create a `webpack.mix.js` file in the root of your project: 461 | 462 | ``` 463 | const mix = require('laravel-mix'); 464 | 465 | /* 466 | |-------------------------------------------------------------------------- 467 | | Mix Asset Management 468 | |-------------------------------------------------------------------------- 469 | | 470 | | Mix provides a clean, fluent API for defining some Webpack build steps 471 | | for your Laravel applications. By default, we are compiling the CSS 472 | | file for the application as well as bundling up all the JS files. 473 | | 474 | */ 475 | 476 | mix.js('resources/js/app.js', 'public/js') 477 | .postCss('resources/css/app.css', 'public/css', [ 478 | // 479 | ]); 480 | ``` 481 | 482 | ### Update NPM scripts 483 | 484 | Update your NPM scripts in `package.json`: 485 | 486 | ```diff 487 | "scripts": { 488 | - "dev": "vite", 489 | - "build": "vite build" 490 | + "dev": "npm run development", 491 | + "development": "mix", 492 | + "watch": "mix watch", 493 | + "watch-poll": "mix watch -- --watch-options-poll=1000", 494 | + "hot": "mix watch --hot", 495 | + "prod": "npm run production", 496 | + "production": "mix --production" 497 | } 498 | ``` 499 | 500 | You should also remove the `type` key by running the following command: 501 | 502 | ```shell 503 | npm pkg delete type 504 | ``` 505 | 506 | #### Inertia 507 | 508 | Vite requires a helper function to import page components which is not required with Laravel Mix. You can remove this as follows: 509 | 510 | ```diff 511 | - import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'; 512 | 513 | createInertiaApp({ 514 | title: (title) => `${title} - ${appName}`, 515 | - resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')), 516 | + resolve: (name) => require(`./Pages/${name}.vue`), 517 | setup({ el, app, props, plugin }) { 518 | return createApp({ render: () => h(app, props) }) 519 | .use(plugin) 520 | .mixin({ methods: { route } }) 521 | .mount(el); 522 | }, 523 | }); 524 | ``` 525 | 526 | ### Update environment variables 527 | 528 | You will need to update the environment variables that are explicitly exposed in your `.env` files and in hosting environments such as Forge to use the `MIX_` prefix instead of `VITE_`: 529 | 530 | ```diff 531 | - VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 532 | - VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 533 | + MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 534 | + MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 535 | ``` 536 | 537 | You will also need to update these references in your JavaScript code to use the new variable name and Node syntax: 538 | 539 | ```diff 540 | - key: import.meta.env.VITE_PUSHER_APP_KEY, 541 | - cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, 542 | + key: process.env.MIX_PUSHER_APP_KEY, 543 | + cluster: process.env.MIX_PUSHER_APP_CLUSTER, 544 | ``` 545 | 546 | ### Remove CSS imports from your JavaScript entry point(s) 547 | 548 | If you are importing your CSS via JavaScript, you will need to remove these statements: 549 | 550 | ```js 551 | - import '../css/app.css'; 552 | ``` 553 | 554 | ### Replace `@vite` with `mix()` 555 | 556 | You will need to replace the `@vite` Blade directive with ` 563 | ``` 564 | 565 | ### Remove Vite and the Laravel Plugin 566 | 567 | Vite and the Laravel Plugin can now be uninstalled: 568 | 569 | ```shell 570 | npm remove vite laravel-vite-plugin 571 | ``` 572 | 573 | Next, you may remove your Vite configuration file: 574 | 575 | ```shell 576 | rm vite.config.js 577 | ``` 578 | 579 | You may also wish to remove any `.gitignore` paths you are no longer using: 580 | 581 | ```gitignore 582 | - /bootstrap/ssr 583 | - /public/build 584 | ``` 585 | 586 | ### Optional: Configure Tailwind 587 | 588 | If you are using Tailwind, perhaps with one of Laravel's starter kits, you will need to update your `tailwind.config.js` configuration file to use CommonJS imports and exports: 589 | 590 | ```diff 591 | - import defaultTheme from 'tailwindcss/defaultTheme'; 592 | - import forms from '@tailwindcss/forms'; 593 | + const defaultTheme = require('tailwindcss/defaultTheme'); 594 | 595 | - export default { 596 | + module.exports = { 597 | content: [ 598 | './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php', 599 | './storage/framework/views/*.php', 600 | './resources/views/**/*.blade.php', 601 | './resources/js/**/*.vue', 602 | ], 603 | 604 | theme: { 605 | extend: { 606 | fontFamily: { 607 | sans: ['Figtree', ...defaultTheme.fontFamily.sans], 608 | }, 609 | }, 610 | }, 611 | 612 | - plugins: [forms], 613 | + plugins: [require('@tailwindcss/forms')], 614 | }; 615 | ``` 616 | 617 | You may also migrate any PostCSS plugins from your `postcss.config.js` file to your `webpack.mix.js` file: 618 | 619 | ```diff 620 | mix.js('resources/js/app.js', 'public/js') 621 | .postCss('resources/css/app.css', 'public/css', [ 622 | - // 623 | + require("tailwindcss"), 624 | ]); 625 | ``` 626 | 627 | > **Note** 628 | > You do not need to include the `autoprefixer` plugin as Laravel Mix includes this by default. 629 | 630 | If you are using other PostCSS plugins, such as `postcss-import`, you will need to include them in your configuration. See the [Laravel Mix PostCSS documentation](https://laravel-mix.com/docs/6.0/postcss) for more information. 631 | 632 | Finally, you may also remove your PostCSS config file: 633 | 634 | ```shell 635 | rm postcss.config.js 636 | ``` 637 | -------------------------------------------------------------------------------- /bin/clean.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { readFileSync, readdirSync, unlinkSync, existsSync } from 'fs' 4 | import { dirname } from 'path' 5 | 6 | /* 7 | * Argv helpers. 8 | */ 9 | 10 | const argument = (name) => { 11 | const index = process.argv.findIndex(argument => argument.startsWith(`--${name}=`)) 12 | 13 | return index === -1 14 | ? undefined 15 | : process.argv[index].substring(`--${name}=`.length) 16 | } 17 | 18 | const option = (name) => process.argv.includes(`--${name}`) 19 | 20 | /* 21 | * Helpers. 22 | */ 23 | const info = option(`quiet`) ? (() => undefined) : console.log 24 | const error = option(`quiet`) ? (() => undefined) : console.error 25 | 26 | /* 27 | * Clean. 28 | */ 29 | 30 | const main = () => { 31 | const manifestPaths = argument(`manifest`) ? [argument(`manifest`)] : (option(`ssr`) 32 | ? [`./bootstrap/ssr/ssr-manifest.json`, `./bootstrap/ssr/manifest.json`] 33 | : [`./public/build/manifest.json`]) 34 | 35 | const foundManifestPath = manifestPaths.find(existsSync) 36 | 37 | if (! foundManifestPath) { 38 | error(`Unable to find manifest file.`) 39 | 40 | process.exit(1) 41 | } 42 | 43 | info(`Reading manifest [${foundManifestPath}].`) 44 | 45 | const manifest = JSON.parse(readFileSync(foundManifestPath).toString()) 46 | 47 | const manifestFiles = Object.keys(manifest) 48 | 49 | const isSsr = Array.isArray(manifest[manifestFiles[0]]) 50 | 51 | isSsr 52 | ? info(`SSR manifest found.`) 53 | : info(`Non-SSR manifest found.`) 54 | 55 | const manifestAssets = isSsr 56 | ? manifestFiles.flatMap(key => manifest[key]) 57 | : manifestFiles.flatMap(key => [ 58 | ...manifest[key].css ?? [], 59 | manifest[key].file, 60 | ]) 61 | 62 | const assetsPath = argument('assets') ?? dirname(foundManifestPath)+'/assets' 63 | 64 | info(`Verify assets in [${assetsPath}].`) 65 | 66 | const existingAssets = readdirSync(assetsPath, { withFileTypes: true }) 67 | 68 | const orphanedAssets = existingAssets.filter(file => file.isFile()) 69 | .filter(file => manifestAssets.findIndex(asset => asset.endsWith(`/${file.name}`)) === -1) 70 | 71 | if (orphanedAssets.length === 0) { 72 | info(`No ophaned assets found.`) 73 | } else { 74 | orphanedAssets.length === 1 75 | ? info(`[${orphanedAssets.length}] orphaned asset found.`) 76 | : info(`[${orphanedAssets.length}] orphaned assets found.`) 77 | 78 | orphanedAssets.forEach(asset => { 79 | const path = `${assetsPath}/${asset.name}` 80 | 81 | option(`dry-run`) 82 | ? info(`Orphaned asset [${path}] would be removed.`) 83 | : info(`Removing orphaned asset [${path}].`) 84 | 85 | if (! option(`dry-run`)) { 86 | unlinkSync(path) 87 | } 88 | }) 89 | } 90 | } 91 | 92 | main() 93 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel-vite-plugin", 3 | "version": "1.3.0", 4 | "description": "Laravel plugin for Vite.", 5 | "keywords": [ 6 | "laravel", 7 | "vite", 8 | "vite-plugin" 9 | ], 10 | "homepage": "https://github.com/laravel/vite-plugin", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/laravel/vite-plugin" 14 | }, 15 | "license": "MIT", 16 | "author": "Laravel", 17 | "type": "module", 18 | "exports": { 19 | ".": { 20 | "types": "./dist/index.d.ts", 21 | "default": "./dist/index.js" 22 | }, 23 | "./inertia-helpers": { 24 | "types": "./inertia-helpers/index.d.ts", 25 | "default": "./inertia-helpers/index.js" 26 | } 27 | }, 28 | "types": "./dist/index.d.ts", 29 | "files": [ 30 | "/dist", 31 | "/inertia-helpers" 32 | ], 33 | "bin": { 34 | "clean-orphaned-assets": "bin/clean.js" 35 | }, 36 | "scripts": { 37 | "build": "npm run build-plugin && npm run build-inertia-helpers", 38 | "build-plugin": "rm -rf dist && npm run build-plugin-types && npm run build-plugin-esm && cp src/dev-server-index.html dist/", 39 | "build-plugin-types": "tsc --emitDeclarationOnly", 40 | "build-plugin-esm": "esbuild src/index.ts --platform=node --format=esm --outfile=dist/index.js", 41 | "build-inertia-helpers": "rm -rf inertia-helpers && tsc --project tsconfig.inertia-helpers.json", 42 | "lint": "eslint --ext .ts ./src ./tests", 43 | "test": "vitest run" 44 | }, 45 | "devDependencies": { 46 | "@types/node": "^18.11.9", 47 | "@typescript-eslint/eslint-plugin": "^5.21.0", 48 | "@typescript-eslint/parser": "^5.21.0", 49 | "esbuild": "0.16.10", 50 | "eslint": "^8.14.0", 51 | "typescript": "^4.6.4", 52 | "vite": "^6.0.0", 53 | "vitest": "^0.34.4" 54 | }, 55 | "peerDependencies": { 56 | "vite": "^5.0.0 || ^6.0.0" 57 | }, 58 | "engines": { 59 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 60 | }, 61 | "dependencies": { 62 | "picocolors": "^1.0.0", 63 | "vite-plugin-full-reload": "^1.1.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/dev-server-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Laravel Vite 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 |
19 |
20 |
21 | 48 |
49 |
50 |

This is the Vite development server that provides Hot Module Replacement for your Laravel application.

51 |

To access your Laravel application, you will need to run a local development server.

52 |

Artisan Serve

53 |

Laravel's local development server powered by PHP's built-in web server.

54 |

Laravel Sail

55 |

A light-weight command-line interface for interacting with Laravel's default Docker development environment.

56 |
57 |
58 |

59 | Your Laravel application's configured APP_URL is:
60 | {{ APP_URL }} 61 |

62 |

Want more information on Laravel's Vite integration?

63 |

64 | Read the docs → 65 |

66 |
67 |
68 |
69 |
70 |
71 | 72 | 73 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import { AddressInfo } from 'net' 3 | import os from 'os' 4 | import { fileURLToPath } from 'url' 5 | import path from 'path' 6 | import colors from 'picocolors' 7 | import { Plugin, loadEnv, UserConfig, ConfigEnv, ResolvedConfig, SSROptions, PluginOption, Rollup } from 'vite' 8 | import fullReload, { Config as FullReloadConfig } from 'vite-plugin-full-reload' 9 | 10 | interface PluginConfig { 11 | /** 12 | * The path or paths of the entry points to compile. 13 | */ 14 | input: Rollup.InputOption 15 | 16 | /** 17 | * Laravel's public directory. 18 | * 19 | * @default 'public' 20 | */ 21 | publicDirectory?: string 22 | 23 | /** 24 | * The public subdirectory where compiled assets should be written. 25 | * 26 | * @default 'build' 27 | */ 28 | buildDirectory?: string 29 | 30 | /** 31 | * The path to the "hot" file. 32 | * 33 | * @default `${publicDirectory}/hot` 34 | */ 35 | hotFile?: string 36 | 37 | /** 38 | * The path of the SSR entry point. 39 | */ 40 | ssr?: Rollup.InputOption 41 | 42 | /** 43 | * The directory where the SSR bundle should be written. 44 | * 45 | * @default 'bootstrap/ssr' 46 | */ 47 | ssrOutputDirectory?: string 48 | 49 | /** 50 | * Configuration for performing full page refresh on blade (or other) file changes. 51 | * 52 | * {@link https://github.com/ElMassimo/vite-plugin-full-reload} 53 | * @default false 54 | */ 55 | refresh?: boolean|string|string[]|RefreshConfig|RefreshConfig[] 56 | 57 | /** 58 | * Utilise the Herd or Valet TLS certificates. 59 | * 60 | * @default null 61 | */ 62 | detectTls?: string|boolean|null, 63 | 64 | /** 65 | * Utilise the Herd or Valet TLS certificates. 66 | * 67 | * @default null 68 | * @deprecated use "detectTls" instead 69 | */ 70 | valetTls?: string|boolean|null, 71 | 72 | /** 73 | * Transform the code while serving. 74 | */ 75 | transformOnServe?: (code: string, url: DevServerUrl) => string, 76 | } 77 | 78 | interface RefreshConfig { 79 | paths: string[], 80 | config?: FullReloadConfig, 81 | } 82 | 83 | interface LaravelPlugin extends Plugin { 84 | config: (config: UserConfig, env: ConfigEnv) => UserConfig 85 | } 86 | 87 | type DevServerUrl = `${'http'|'https'}://${string}:${number}` 88 | 89 | let exitHandlersBound = false 90 | 91 | export const refreshPaths = [ 92 | 'app/Livewire/**', 93 | 'app/View/Components/**', 94 | 'lang/**', 95 | 'resources/lang/**', 96 | 'resources/views/**', 97 | 'routes/**', 98 | ].filter(path => fs.existsSync(path.replace(/\*\*$/, ''))) 99 | 100 | /** 101 | * Laravel plugin for Vite. 102 | * 103 | * @param config - A config object or relative path(s) of the scripts to be compiled. 104 | */ 105 | export default function laravel(config: string|string[]|PluginConfig): [LaravelPlugin, ...Plugin[]] { 106 | const pluginConfig = resolvePluginConfig(config) 107 | 108 | return [ 109 | resolveLaravelPlugin(pluginConfig), 110 | ...resolveFullReloadConfig(pluginConfig) as Plugin[], 111 | ]; 112 | } 113 | 114 | /** 115 | * Resolve the Laravel Plugin configuration. 116 | */ 117 | function resolveLaravelPlugin(pluginConfig: Required): LaravelPlugin { 118 | let viteDevServerUrl: DevServerUrl 119 | let resolvedConfig: ResolvedConfig 120 | let userConfig: UserConfig 121 | 122 | const defaultAliases: Record = { 123 | '@': '/resources/js', 124 | }; 125 | 126 | return { 127 | name: 'laravel', 128 | enforce: 'post', 129 | config: (config, { command, mode }) => { 130 | userConfig = config 131 | const ssr = !! userConfig.build?.ssr 132 | const env = loadEnv(mode, userConfig.envDir || process.cwd(), '') 133 | const assetUrl = env.ASSET_URL ?? '' 134 | const serverConfig = command === 'serve' 135 | ? (resolveDevelopmentEnvironmentServerConfig(pluginConfig.detectTls) ?? resolveEnvironmentServerConfig(env)) 136 | : undefined 137 | 138 | ensureCommandShouldRunInEnvironment(command, env) 139 | 140 | return { 141 | base: userConfig.base ?? (command === 'build' ? resolveBase(pluginConfig, assetUrl) : ''), 142 | publicDir: userConfig.publicDir ?? false, 143 | build: { 144 | manifest: userConfig.build?.manifest ?? (ssr ? false : 'manifest.json'), 145 | ssrManifest: userConfig.build?.ssrManifest ?? (ssr ? 'ssr-manifest.json' : false), 146 | outDir: userConfig.build?.outDir ?? resolveOutDir(pluginConfig, ssr), 147 | rollupOptions: { 148 | input: userConfig.build?.rollupOptions?.input ?? resolveInput(pluginConfig, ssr) 149 | }, 150 | assetsInlineLimit: userConfig.build?.assetsInlineLimit ?? 0, 151 | }, 152 | server: { 153 | origin: userConfig.server?.origin ?? 'http://__laravel_vite_placeholder__.test', 154 | cors: userConfig.server?.cors ?? { 155 | origin: userConfig.server?.origin ?? [ 156 | /^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/, // Copied from Vite itself. We can import this once we drop 5.0 support and require Vite 6.1+. Source: https://github.com/vitejs/vite/blob/0c854645bd17960abbe8f01b602d1a1da1a2b9fd/packages/vite/src/node/constants.ts#L200-L201 157 | ...(env.APP_URL ? [env.APP_URL] : []), // * (APP_URL="http://my-app.tld") 158 | /^https?:\/\/.*\.test(:\d+)?$/, // Valet / Herd (SCHEME://*.test:PORT) 159 | ], 160 | }, 161 | ...(process.env.LARAVEL_SAIL ? { 162 | host: userConfig.server?.host ?? '0.0.0.0', 163 | port: userConfig.server?.port ?? (env.VITE_PORT ? parseInt(env.VITE_PORT) : 5173), 164 | strictPort: userConfig.server?.strictPort ?? true, 165 | } : undefined), 166 | ...(serverConfig ? { 167 | host: userConfig.server?.host ?? serverConfig.host, 168 | hmr: userConfig.server?.hmr === false ? false : { 169 | ...serverConfig.hmr, 170 | ...(userConfig.server?.hmr === true ? {} : userConfig.server?.hmr), 171 | }, 172 | https: userConfig.server?.https ?? serverConfig.https, 173 | } : undefined), 174 | }, 175 | resolve: { 176 | alias: Array.isArray(userConfig.resolve?.alias) 177 | ? [ 178 | ...userConfig.resolve?.alias ?? [], 179 | ...Object.keys(defaultAliases).map(alias => ({ 180 | find: alias, 181 | replacement: defaultAliases[alias] 182 | })) 183 | ] 184 | : { 185 | ...defaultAliases, 186 | ...userConfig.resolve?.alias, 187 | } 188 | }, 189 | ssr: { 190 | noExternal: noExternalInertiaHelpers(userConfig), 191 | }, 192 | } 193 | }, 194 | configResolved(config) { 195 | resolvedConfig = config 196 | }, 197 | transform(code) { 198 | if (resolvedConfig.command === 'serve') { 199 | code = code.replace(/http:\/\/__laravel_vite_placeholder__\.test/g, viteDevServerUrl) 200 | 201 | return pluginConfig.transformOnServe(code, viteDevServerUrl) 202 | } 203 | }, 204 | configureServer(server) { 205 | const envDir = resolvedConfig.envDir || process.cwd() 206 | const appUrl = loadEnv(resolvedConfig.mode, envDir, 'APP_URL').APP_URL ?? 'undefined' 207 | 208 | server.httpServer?.once('listening', () => { 209 | const address = server.httpServer?.address() 210 | 211 | const isAddressInfo = (x: string|AddressInfo|null|undefined): x is AddressInfo => typeof x === 'object' 212 | if (isAddressInfo(address)) { 213 | viteDevServerUrl = userConfig.server?.origin ? userConfig.server.origin as DevServerUrl : resolveDevServerUrl(address, server.config, userConfig) 214 | 215 | fs.writeFileSync(pluginConfig.hotFile, `${viteDevServerUrl}${server.config.base.replace(/\/$/, '')}`) 216 | 217 | setTimeout(() => { 218 | server.config.logger.info(`\n ${colors.red(`${colors.bold('LARAVEL')} ${laravelVersion()}`)} ${colors.dim('plugin')} ${colors.bold(`v${pluginVersion()}`)}`) 219 | server.config.logger.info('') 220 | server.config.logger.info(` ${colors.green('➜')} ${colors.bold('APP_URL')}: ${colors.cyan(appUrl.replace(/:(\d+)/, (_, port) => `:${colors.bold(port)}`))}`) 221 | 222 | if (typeof resolvedConfig.server.https === 'object' && typeof resolvedConfig.server.https.key === 'string') { 223 | if (resolvedConfig.server.https.key.startsWith(herdMacConfigPath()) || resolvedConfig.server.https.key.startsWith(herdWindowsConfigPath())) { 224 | server.config.logger.info(` ${colors.green('➜')} Using Herd certificate to secure Vite.`) 225 | } 226 | 227 | if (resolvedConfig.server.https.key.startsWith(valetMacConfigPath()) || resolvedConfig.server.https.key.startsWith(valetLinuxConfigPath())) { 228 | server.config.logger.info(` ${colors.green('➜')} Using Valet certificate to secure Vite.`) 229 | } 230 | } 231 | }, 100) 232 | } 233 | }) 234 | 235 | if (! exitHandlersBound) { 236 | const clean = () => { 237 | if (fs.existsSync(pluginConfig.hotFile)) { 238 | fs.rmSync(pluginConfig.hotFile) 239 | } 240 | } 241 | 242 | process.on('exit', clean) 243 | process.on('SIGINT', () => process.exit()) 244 | process.on('SIGTERM', () => process.exit()) 245 | process.on('SIGHUP', () => process.exit()) 246 | 247 | exitHandlersBound = true 248 | } 249 | 250 | return () => server.middlewares.use((req, res, next) => { 251 | if (req.url === '/index.html') { 252 | res.statusCode = 404 253 | 254 | res.end( 255 | fs.readFileSync(path.join(dirname(), 'dev-server-index.html')).toString().replace(/{{ APP_URL }}/g, appUrl) 256 | ) 257 | } 258 | 259 | next() 260 | }) 261 | } 262 | } 263 | } 264 | 265 | /** 266 | * Validate the command can run in the given environment. 267 | */ 268 | function ensureCommandShouldRunInEnvironment(command: 'build'|'serve', env: Record): void { 269 | if (command === 'build' || env.LARAVEL_BYPASS_ENV_CHECK === '1') { 270 | return; 271 | } 272 | 273 | if (typeof env.LARAVEL_VAPOR !== 'undefined') { 274 | throw Error('You should not run the Vite HMR server on Vapor. You should build your assets for production instead. To disable this ENV check you may set LARAVEL_BYPASS_ENV_CHECK=1'); 275 | } 276 | 277 | if (typeof env.LARAVEL_FORGE !== 'undefined') { 278 | throw Error('You should not run the Vite HMR server in your Forge deployment script. You should build your assets for production instead. To disable this ENV check you may set LARAVEL_BYPASS_ENV_CHECK=1'); 279 | } 280 | 281 | if (typeof env.LARAVEL_ENVOYER !== 'undefined') { 282 | throw Error('You should not run the Vite HMR server in your Envoyer hook. You should build your assets for production instead. To disable this ENV check you may set LARAVEL_BYPASS_ENV_CHECK=1') 283 | } 284 | 285 | if (typeof env.CI !== 'undefined') { 286 | throw Error('You should not run the Vite HMR server in CI environments. You should build your assets for production instead. To disable this ENV check you may set LARAVEL_BYPASS_ENV_CHECK=1') 287 | } 288 | } 289 | 290 | /** 291 | * The version of Laravel being run. 292 | */ 293 | function laravelVersion(): string { 294 | try { 295 | const composer = JSON.parse(fs.readFileSync('composer.lock').toString()) 296 | 297 | return composer.packages?.find((composerPackage: {name: string}) => composerPackage.name === 'laravel/framework')?.version ?? '' 298 | } catch { 299 | return '' 300 | } 301 | } 302 | 303 | /** 304 | * The version of the Laravel Vite plugin being run. 305 | */ 306 | function pluginVersion(): string { 307 | try { 308 | return JSON.parse(fs.readFileSync(path.join(dirname(), '../package.json')).toString())?.version 309 | } catch { 310 | return '' 311 | } 312 | } 313 | 314 | /** 315 | * Convert the users configuration into a standard structure with defaults. 316 | */ 317 | function resolvePluginConfig(config: string|string[]|PluginConfig): Required { 318 | if (typeof config === 'undefined') { 319 | throw new Error('laravel-vite-plugin: missing configuration.') 320 | } 321 | 322 | if (typeof config === 'string' || Array.isArray(config)) { 323 | config = { input: config, ssr: config } 324 | } 325 | 326 | if (typeof config.input === 'undefined') { 327 | throw new Error('laravel-vite-plugin: missing configuration for "input".') 328 | } 329 | 330 | if (typeof config.publicDirectory === 'string') { 331 | config.publicDirectory = config.publicDirectory.trim().replace(/^\/+/, '') 332 | 333 | if (config.publicDirectory === '') { 334 | throw new Error('laravel-vite-plugin: publicDirectory must be a subdirectory. E.g. \'public\'.') 335 | } 336 | } 337 | 338 | if (typeof config.buildDirectory === 'string') { 339 | config.buildDirectory = config.buildDirectory.trim().replace(/^\/+/, '').replace(/\/+$/, '') 340 | 341 | if (config.buildDirectory === '') { 342 | throw new Error('laravel-vite-plugin: buildDirectory must be a subdirectory. E.g. \'build\'.') 343 | } 344 | } 345 | 346 | if (typeof config.ssrOutputDirectory === 'string') { 347 | config.ssrOutputDirectory = config.ssrOutputDirectory.trim().replace(/^\/+/, '').replace(/\/+$/, '') 348 | } 349 | 350 | if (config.refresh === true) { 351 | config.refresh = [{ paths: refreshPaths }] 352 | } 353 | 354 | return { 355 | input: config.input, 356 | publicDirectory: config.publicDirectory ?? 'public', 357 | buildDirectory: config.buildDirectory ?? 'build', 358 | ssr: config.ssr ?? config.input, 359 | ssrOutputDirectory: config.ssrOutputDirectory ?? 'bootstrap/ssr', 360 | refresh: config.refresh ?? false, 361 | hotFile: config.hotFile ?? path.join((config.publicDirectory ?? 'public'), 'hot'), 362 | valetTls: config.valetTls ?? null, 363 | detectTls: config.detectTls ?? config.valetTls ?? null, 364 | transformOnServe: config.transformOnServe ?? ((code) => code), 365 | } 366 | } 367 | 368 | /** 369 | * Resolve the Vite base option from the configuration. 370 | */ 371 | function resolveBase(config: Required, assetUrl: string): string { 372 | return assetUrl + (! assetUrl.endsWith('/') ? '/' : '') + config.buildDirectory + '/' 373 | } 374 | 375 | /** 376 | * Resolve the Vite input path from the configuration. 377 | */ 378 | function resolveInput(config: Required, ssr: boolean): Rollup.InputOption|undefined { 379 | if (ssr) { 380 | return config.ssr 381 | } 382 | 383 | return config.input 384 | } 385 | 386 | /** 387 | * Resolve the Vite outDir path from the configuration. 388 | */ 389 | function resolveOutDir(config: Required, ssr: boolean): string|undefined { 390 | if (ssr) { 391 | return config.ssrOutputDirectory 392 | } 393 | 394 | return path.join(config.publicDirectory, config.buildDirectory) 395 | } 396 | 397 | function resolveFullReloadConfig({ refresh: config }: Required): PluginOption[]{ 398 | if (typeof config === 'boolean') { 399 | return []; 400 | } 401 | 402 | if (typeof config === 'string') { 403 | config = [{ paths: [config]}] 404 | } 405 | 406 | if (! Array.isArray(config)) { 407 | config = [config] 408 | } 409 | 410 | if (config.some(c => typeof c === 'string')) { 411 | config = [{ paths: config }] as RefreshConfig[] 412 | } 413 | 414 | return (config as RefreshConfig[]).flatMap(c => { 415 | const plugin = fullReload(c.paths, c.config) 416 | 417 | /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */ 418 | /** @ts-ignore */ 419 | plugin.__laravel_plugin_config = c 420 | 421 | return plugin 422 | }) 423 | } 424 | 425 | /** 426 | * Resolve the dev server URL from the server address and configuration. 427 | */ 428 | function resolveDevServerUrl(address: AddressInfo, config: ResolvedConfig, userConfig: UserConfig): DevServerUrl { 429 | const configHmrProtocol = typeof config.server.hmr === 'object' ? config.server.hmr.protocol : null 430 | const clientProtocol = configHmrProtocol ? (configHmrProtocol === 'wss' ? 'https' : 'http') : null 431 | const serverProtocol = config.server.https ? 'https' : 'http' 432 | const protocol = clientProtocol ?? serverProtocol 433 | 434 | const configHmrHost = typeof config.server.hmr === 'object' ? config.server.hmr.host : null 435 | const configHost = typeof config.server.host === 'string' ? config.server.host : null 436 | const sailHost = process.env.LARAVEL_SAIL && ! userConfig.server?.host ? 'localhost' : null 437 | const serverAddress = isIpv6(address) ? `[${address.address}]` : address.address 438 | const host = configHmrHost ?? sailHost ?? configHost ?? serverAddress 439 | 440 | const configHmrClientPort = typeof config.server.hmr === 'object' ? config.server.hmr.clientPort : null 441 | const port = configHmrClientPort ?? address.port 442 | 443 | return `${protocol}://${host}:${port}` 444 | } 445 | 446 | function isIpv6(address: AddressInfo): boolean { 447 | return address.family === 'IPv6' 448 | // In node >=18.0 <18.4 this was an integer value. This was changed in a minor version. 449 | // See: https://github.com/laravel/vite-plugin/issues/103 450 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 451 | // @ts-ignore-next-line 452 | || address.family === 6; 453 | } 454 | 455 | /** 456 | * Add the Inertia helpers to the list of SSR dependencies that aren't externalized. 457 | * 458 | * @see https://vitejs.dev/guide/ssr.html#ssr-externals 459 | */ 460 | function noExternalInertiaHelpers(config: UserConfig): true|Array { 461 | /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */ 462 | /* @ts-ignore */ 463 | const userNoExternal = (config.ssr as SSROptions|undefined)?.noExternal 464 | const pluginNoExternal = ['laravel-vite-plugin'] 465 | 466 | if (userNoExternal === true) { 467 | return true 468 | } 469 | 470 | if (typeof userNoExternal === 'undefined') { 471 | return pluginNoExternal 472 | } 473 | 474 | return [ 475 | ...(Array.isArray(userNoExternal) ? userNoExternal : [userNoExternal]), 476 | ...pluginNoExternal, 477 | ] 478 | } 479 | 480 | /** 481 | * Resolve the server config from the environment. 482 | */ 483 | function resolveEnvironmentServerConfig(env: Record): { 484 | hmr?: { host: string } 485 | host?: string, 486 | https?: { cert: Buffer, key: Buffer } 487 | }|undefined { 488 | if (! env.VITE_DEV_SERVER_KEY && ! env.VITE_DEV_SERVER_CERT) { 489 | return 490 | } 491 | 492 | if (! fs.existsSync(env.VITE_DEV_SERVER_KEY) || ! fs.existsSync(env.VITE_DEV_SERVER_CERT)) { 493 | throw Error(`Unable to find the certificate files specified in your environment. Ensure you have correctly configured VITE_DEV_SERVER_KEY: [${env.VITE_DEV_SERVER_KEY}] and VITE_DEV_SERVER_CERT: [${env.VITE_DEV_SERVER_CERT}].`) 494 | } 495 | 496 | const host = resolveHostFromEnv(env) 497 | 498 | if (! host) { 499 | throw Error(`Unable to determine the host from the environment's APP_URL: [${env.APP_URL}].`) 500 | } 501 | 502 | return { 503 | hmr: { host }, 504 | host, 505 | https: { 506 | key: fs.readFileSync(env.VITE_DEV_SERVER_KEY), 507 | cert: fs.readFileSync(env.VITE_DEV_SERVER_CERT), 508 | }, 509 | } 510 | } 511 | 512 | /** 513 | * Resolve the host name from the environment. 514 | */ 515 | function resolveHostFromEnv(env: Record): string|undefined 516 | { 517 | try { 518 | return new URL(env.APP_URL).host 519 | } catch { 520 | return 521 | } 522 | } 523 | 524 | /** 525 | * Resolve the Herd or Valet server config for the given host. 526 | */ 527 | function resolveDevelopmentEnvironmentServerConfig(host: string|boolean|null): { 528 | hmr?: { host: string } 529 | host?: string, 530 | https?: { cert: string, key: string } 531 | }|undefined { 532 | if (host === false) { 533 | return 534 | } 535 | 536 | const configPath = determineDevelopmentEnvironmentConfigPath(); 537 | 538 | if (typeof configPath === 'undefined' && host === null) { 539 | return 540 | } 541 | 542 | if (typeof configPath === 'undefined') { 543 | throw Error(`Unable to find the Herd or Valet configuration directory. Please check they are correctly installed.`) 544 | } 545 | 546 | const resolvedHost = host === true || host === null 547 | ? path.basename(process.cwd()) + '.' + resolveDevelopmentEnvironmentTld(configPath) 548 | : host 549 | 550 | const keyPath = path.resolve(configPath, 'Certificates', `${resolvedHost}.key`) 551 | const certPath = path.resolve(configPath, 'Certificates', `${resolvedHost}.crt`) 552 | 553 | if (! fs.existsSync(keyPath) || ! fs.existsSync(certPath)) { 554 | if (host === null) { 555 | return 556 | } 557 | 558 | if (configPath === herdMacConfigPath() || configPath === herdWindowsConfigPath()) { 559 | throw Error(`Unable to find certificate files for your host [${resolvedHost}] in the [${configPath}/Certificates] directory. Ensure you have secured the site via the Herd UI.`) 560 | } else if (typeof host === 'string') { 561 | throw Error(`Unable to find certificate files for your host [${resolvedHost}] in the [${configPath}/Certificates] directory. Ensure you have secured the site by running \`valet secure ${host}\`.`) 562 | } else { 563 | throw Error(`Unable to find certificate files for your host [${resolvedHost}] in the [${configPath}/Certificates] directory. Ensure you have secured the site by running \`valet secure\`.`) 564 | } 565 | } 566 | 567 | return { 568 | hmr: { host: resolvedHost }, 569 | host: resolvedHost, 570 | https: { 571 | key: keyPath, 572 | cert: certPath, 573 | }, 574 | } 575 | } 576 | 577 | /** 578 | * Resolve the path to the Herd or Valet configuration directory. 579 | */ 580 | function determineDevelopmentEnvironmentConfigPath(): string|undefined { 581 | if (fs.existsSync(herdMacConfigPath())) { 582 | return herdMacConfigPath() 583 | } 584 | 585 | if (fs.existsSync(herdWindowsConfigPath())) { 586 | return herdWindowsConfigPath() 587 | } 588 | 589 | if (fs.existsSync(valetMacConfigPath())) { 590 | return valetMacConfigPath() 591 | } 592 | 593 | if (fs.existsSync(valetLinuxConfigPath())) { 594 | return valetLinuxConfigPath() 595 | } 596 | } 597 | 598 | /** 599 | * Resolve the TLD via the config path. 600 | */ 601 | function resolveDevelopmentEnvironmentTld(configPath: string): string { 602 | const configFile = path.resolve(configPath, 'config.json') 603 | 604 | if (! fs.existsSync(configFile)) { 605 | throw Error(`Unable to find the configuration file [${configFile}].`) 606 | } 607 | 608 | const config: { tld: string } = JSON.parse(fs.readFileSync(configFile, 'utf-8')) 609 | 610 | return config.tld 611 | } 612 | 613 | /** 614 | * The directory of the current file. 615 | */ 616 | function dirname(): string { 617 | return fileURLToPath(new URL('.', import.meta.url)) 618 | } 619 | 620 | /** 621 | * Herd's Mac configuration directory. 622 | */ 623 | function herdMacConfigPath(): string { 624 | return path.resolve(os.homedir(), 'Library', 'Application Support', 'Herd', 'config', 'valet') 625 | } 626 | 627 | /** 628 | * Herd's Windows configuration directory. 629 | */ 630 | function herdWindowsConfigPath(): string { 631 | return path.resolve(os.homedir(), ".config", "herd", "config", "valet") 632 | } 633 | 634 | /** 635 | * Valet's Mac configuration directory. 636 | */ 637 | function valetMacConfigPath(): string { 638 | return path.resolve(os.homedir(), '.config', 'valet') 639 | } 640 | 641 | /** 642 | * Valet Linux's configuration directory. 643 | */ 644 | function valetLinuxConfigPath(): string { 645 | return path.resolve(os.homedir(), '.valet') 646 | } 647 | -------------------------------------------------------------------------------- /src/inertia-helpers/index.ts: -------------------------------------------------------------------------------- 1 | export async function resolvePageComponent(path: string|string[], pages: Record | (() => Promise)>): Promise { 2 | for (const p of (Array.isArray(path) ? path : [path])) { 3 | const page = pages[p] 4 | 5 | if (typeof page === 'undefined') { 6 | continue 7 | } 8 | 9 | return typeof page === 'function' ? page() : page 10 | } 11 | 12 | throw new Error(`Page not found: ${path}`) 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.inertia-helpers.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "inertia-helpers" 5 | }, 6 | "include": [ 7 | "./src/inertia-helpers/index.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target": "ES2020", 5 | "module": "NodeNext", 6 | "moduleResolution": "NodeNext", 7 | "resolveJsonModule": true, 8 | "strict": true, 9 | "declaration": true, 10 | "esModuleInterop": true 11 | }, 12 | "include": [ 13 | "./src/index.ts" 14 | ] 15 | } 16 | --------------------------------------------------------------------------------