Skip to content

Commit 28d78e8

Browse files
authored
Merge pull request #14 from laravel/remove-default-entrypoint
Remove default entry point
2 parents 902a2ef + 5f9dfb3 commit 28d78e8

File tree

3 files changed

+77
-55
lines changed

3 files changed

+77
-55
lines changed

UPGRADE.md

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ import laravel from 'laravel-vite-plugin'
3434

3535
export default defineConfig({
3636
plugins: [
37-
laravel(),
37+
laravel([
38+
'resources/css/app.css',
39+
'resources/js/app.js',
40+
]),
3841
// react(),
3942
// vue({
4043
// template: {
@@ -48,7 +51,7 @@ export default defineConfig({
4851
})
4952
```
5053

51-
If your entry point is not `resources/js/app.js`, you should read the [entry point docs](https://github.com/laravel/vite-plugin/blob/docs/docs/vite.md#entry-points) to learn how to configure the Laravel plugin for your project.
54+
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).
5255

5356
### Update NPM Scripts
5457

@@ -116,14 +119,17 @@ You will also need to update these references in your JavaScript code to use the
116119
+ cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
117120
```
118121

119-
### Import your CSS from your JavaScript entry point(s)
122+
### Importing your CSS from your JavaScript entry point(s)
120123

121-
Vite expects your CSS files to be imported via JavaScript, such as your `resources/js/app.js` entry point:
124+
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:
122125

123-
```js
124-
import '../css/app.css'
126+
```diff
127+
import './bootstrap';
128+
+ import '../css/app.css';
125129
```
126130

131+
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.
132+
127133
### Replace `mix()` with `@vite`
128134

129135
When using Vite, you will need to use the `@vite` Blade directive instead of the `mix()` helper.
@@ -133,18 +139,18 @@ This will automatically detect whether you are running in serve or build mode an
133139
```diff
134140
- <link rel="stylesheet" href="{{ mix('css/app.css') }}">
135141
- <script src="{{ mix('js/app.js') }}" defer></script>
136-
+ @vite
142+
+ @vite(['resources/css/app.css', 'resources/js/app.js'])
137143
```
138144

139-
If your entry point is not `resources/js/app.js`, you should read the [entry point docs](https://github.com/laravel/vite-plugin/blob/docs/docs/vite.md#entry-points) to learn how to use the `@vite` directive with different entry points.
145+
The entry points should match those used in your `vite.config.js`.
140146

141147
#### React
142148

143149
If you are using React and hot-module replacement, you will need to include an additional directive *before* the `@vite` directive:
144150

145151
```html
146152
@viteReactRefresh
147-
@vite
153+
@vite('resources/js/app.jsx')
148154
```
149155

150156
This loads a React "refresh runtime" in development mode only, which is required for hot module replacement to work correctly.
@@ -212,7 +218,21 @@ You may remove your dedicated Laravel Mix SSR configuration:
212218
rm webpack.ssr.mix.js
213219
```
214220

215-
In most cases you won't need a dedicated SSR configuration file with Vite. If your SSR entry point is not `resources/js/ssr.js`, you should read the [entry point docs](https://github.com/laravel/vite-plugin/blob/docs/docs/vite.md#entry-points) to learn how to configure the Laravel plugin for your project.
221+
In most cases you won't need a dedicated SSR configuration file with Vite. You can specify your SSR entry point by passing a configuration option to the Laravel plugin.
222+
223+
```js
224+
import { defineConfig } from 'vite'
225+
import laravel from 'laravel-vite-plugin'
226+
227+
export default defineConfig({
228+
plugins: [
229+
laravel({
230+
input: 'resources/js/app.js',
231+
ssr: 'resources/js/ssr.js',
232+
}),
233+
],
234+
})
235+
```
216236

217237
You may wish to add the following additional scripts to your `package.json`:
218238

@@ -342,7 +362,7 @@ You will need to replace the `@vite` Blade directive with `<script>` and `<link
342362

343363
```diff
344364
- @viteReactRefresh
345-
- @vite
365+
- @vite('resources/js/app.js')
346366
+ <link rel="stylesheet" href="{{ mix('css/app.css') }}">
347367
+ <script src="{{ mix('js/app.js') }}" defer></script>
348368
```

src/index.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,34 @@ import { Plugin, loadEnv, UserConfig, ConfigEnv, Manifest, ResolvedConfig } from
77
interface PluginConfig {
88
/**
99
* The path or paths of the entry points to compile.
10-
*
11-
* @default ['resources/css/app.css', 'resources/js/app.js']
1210
*/
13-
input: string|string[]|undefined
11+
input: string|string[]
1412

1513
/**
1614
* Laravel's public directory.
1715
*
1816
* @default 'public'
1917
*/
20-
publicDirectory: string
18+
publicDirectory?: string
2119

2220
/**
2321
* The public subdirectory where compiled assets should be written.
2422
*
2523
* @default 'build'
2624
*/
27-
buildDirectory: string
25+
buildDirectory?: string
2826

2927
/**
3028
* The path of the SSR entry point.
31-
*
32-
* @default 'resources/js/ssr.js'
3329
*/
34-
ssr: string|string[]|undefined
30+
ssr?: string|string[]
3531

3632
/**
3733
* The directory where the SSR bundle should be written.
3834
*
3935
* @default 'storage/ssr'
4036
*/
41-
ssrOutputDirectory: string
37+
ssrOutputDirectory?: string
4238
}
4339

4440
interface LaravelPlugin extends Plugin {
@@ -50,7 +46,7 @@ interface LaravelPlugin extends Plugin {
5046
*
5147
* @param config - A config object or relative path(s) of the scripts to be compiled.
5248
*/
53-
export default function laravel(config?: string|string[]|Partial<PluginConfig>): LaravelPlugin {
49+
export default function laravel(config: string|string[]|PluginConfig): LaravelPlugin {
5450
const pluginConfig = resolvePluginConfig(config)
5551
let viteDevServerUrl: string
5652
let resolvedConfig: ResolvedConfig
@@ -203,24 +199,32 @@ function laravelVersion(): string {
203199
/**
204200
* Convert the users configuration into a standard structure with defaults.
205201
*/
206-
function resolvePluginConfig(config?: string|string[]|Partial<PluginConfig>): PluginConfig {
207-
if (typeof config === 'undefined' || typeof config === 'string' || Array.isArray(config)) {
202+
function resolvePluginConfig(config: string|string[]|PluginConfig): Required<PluginConfig> {
203+
if (typeof config === 'undefined') {
204+
throw new Error('laravel-vite-plugin: missing configuration.')
205+
}
206+
207+
if (typeof config === 'string' || Array.isArray(config)) {
208208
config = { input: config, ssr: config }
209209
}
210210

211+
if (typeof config.input === 'undefined') {
212+
throw new Error('laravel-vite-plugin: missing configuration for "input".')
213+
}
214+
211215
if (typeof config.publicDirectory === 'string') {
212216
config.publicDirectory = config.publicDirectory.trim().replace(/^\/+/, '')
213217

214218
if (config.publicDirectory === '') {
215-
throw new Error('publicDirectory must be a subdirectory. E.g. \'public\'.')
219+
throw new Error('laravel-vite-plugin: publicDirectory must be a subdirectory. E.g. \'public\'.')
216220
}
217221
}
218222

219223
if (typeof config.buildDirectory === 'string') {
220224
config.buildDirectory = config.buildDirectory.trim().replace(/^\/+/, '').replace(/\/+$/, '')
221225

222226
if (config.buildDirectory === '') {
223-
throw new Error('buildDirectory must be a subdirectory. E.g. \'build\'.')
227+
throw new Error('laravel-vite-plugin: buildDirectory must be a subdirectory. E.g. \'build\'.')
224228
}
225229
}
226230

@@ -229,27 +233,27 @@ function resolvePluginConfig(config?: string|string[]|Partial<PluginConfig>): Pl
229233
}
230234

231235
return {
232-
input: config.input ?? ['resources/css/app.css', 'resources/js/app.js'],
236+
input: config.input,
233237
publicDirectory: config.publicDirectory ?? 'public',
234238
buildDirectory: config.buildDirectory ?? 'build',
235-
ssr: config.ssr ?? 'resources/js/ssr.js',
239+
ssr: config.ssr ?? config.input,
236240
ssrOutputDirectory: config.ssrOutputDirectory ?? 'storage/ssr',
237241
}
238242
}
239243

240244
/**
241245
* Resolve the Vite base option from the configuration.
242246
*/
243-
function resolveBase(config: PluginConfig, assetUrl: string): string {
247+
function resolveBase(config: Required<PluginConfig>, assetUrl: string): string {
244248
return assetUrl + (! assetUrl.endsWith('/') ? '/' : '') + config.buildDirectory + '/'
245249
}
246250

247251
/**
248252
* Resolve the Vite input path from the configuration.
249253
*/
250-
function resolveInput(config: PluginConfig, ssr: boolean): string|string[]|undefined {
254+
function resolveInput(config: Required<PluginConfig>, ssr: boolean): string|string[]|undefined {
251255
if (ssr) {
252-
return config.ssr ?? config.input
256+
return config.ssr
253257
}
254258

255259
return config.input
@@ -258,7 +262,7 @@ function resolveInput(config: PluginConfig, ssr: boolean): string|string[]|undef
258262
/**
259263
* Resolve the Vite outDir path from the configuration.
260264
*/
261-
function resolveOutDir(config: PluginConfig, ssr: boolean): string|undefined {
265+
function resolveOutDir(config: Required<PluginConfig>, ssr: boolean): string|undefined {
262266
if (ssr) {
263267
return config.ssrOutputDirectory
264268
}

tests/index.test.ts

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,16 @@ describe('laravel-vite-plugin', () => {
77
vi.clearAllMocks()
88
})
99

10-
it('provides sensible default values', () => {
11-
const plugin = laravel()
12-
expect(plugin.name).toBe('laravel')
13-
14-
const buildConfig = plugin.config({}, { command: 'build', mode: 'production' })
15-
expect(buildConfig.base).toBe('/build/')
16-
expect(buildConfig.build.manifest).toBe(true)
17-
expect(buildConfig.build.outDir).toBe('public/build')
18-
expect(buildConfig.build.rollupOptions.input).toEqual(['resources/css/app.css', 'resources/js/app.js'])
19-
20-
const serveConfig = plugin.config({}, { command: 'serve', mode: 'development' })
21-
expect(serveConfig.base).toBe('')
22-
expect(buildConfig.server.host).toBeUndefined()
23-
expect(buildConfig.server.port).toBeUndefined()
24-
expect(buildConfig.server.strictPort).toBeUndefined()
10+
it('handles missing configuration', () => {
11+
/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */
12+
/* @ts-ignore */
13+
expect(() => laravel())
14+
.toThrowError('laravel-vite-plugin: missing configuration.');
2515

26-
const ssrConfig = plugin.config({ build: { ssr: true } }, { command: 'build', mode: 'production' })
27-
expect(ssrConfig.base).toBe('/build/')
28-
expect(ssrConfig.build.manifest).toBe(false)
29-
expect(ssrConfig.build.outDir).toBe('storage/ssr')
30-
expect(ssrConfig.build.rollupOptions.input).toBe('resources/js/ssr.js')
16+
/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */
17+
/* @ts-ignore */
18+
expect(() => laravel({}))
19+
.toThrowError('laravel-vite-plugin: missing configuration for "input".');
3120
})
3221

3322
it('accepts a single input', () => {
@@ -94,6 +83,14 @@ describe('laravel-vite-plugin', () => {
9483
expect(ssrConfig.build.rollupOptions.input).toBe('resources/js/ssr.js')
9584
})
9685

86+
it('uses the default entry point when ssr entry point is not provided', () => {
87+
// This is support users who may want a dedicated Vite config for SSR.
88+
const plugin = laravel('resources/js/ssr.js')
89+
90+
const ssrConfig = plugin.config({ build: { ssr: true } }, { command: 'build', mode: 'production' })
91+
expect(ssrConfig.build.rollupOptions.input).toBe('resources/js/ssr.js')
92+
})
93+
9794
it('prefixes the base with ASSET_URL in production mode', () => {
9895
process.env.ASSET_URL = 'http://example.com'
9996
const plugin = laravel('resources/js/app.js')
@@ -108,17 +105,18 @@ describe('laravel-vite-plugin', () => {
108105
})
109106

110107
it('prevents setting an empty publicDirectory', () => {
111-
expect(() => laravel({ publicDirectory: '' }))
108+
expect(() => laravel({ input: 'resources/js/app.js', publicDirectory: '' }))
112109
.toThrowError('publicDirectory must be a subdirectory');
113110
})
114111

115112
it('prevents setting an empty buildDirectory', () => {
116-
expect(() => laravel({ buildDirectory: '' }))
113+
expect(() => laravel({ input: 'resources/js/app.js', buildDirectory: '' }))
117114
.toThrowError('buildDirectory must be a subdirectory');
118115
})
119116

120117
it('handles surrounding slashes on directories', () => {
121118
const plugin = laravel({
119+
input: 'resources/js/app.js',
122120
publicDirectory: '/public/test/',
123121
buildDirectory: '/build/test/',
124122
ssrOutputDirectory: '/ssr-output/test/',
@@ -197,7 +195,7 @@ describe('laravel-vite-plugin', () => {
197195

198196
it('configures the Vite server when inside a Sail container', () => {
199197
process.env.LARAVEL_SAIL = '1'
200-
const plugin = laravel()
198+
const plugin = laravel('resources/js/app.js')
201199

202200
const config = plugin.config({}, { command: 'serve', mode: 'development' })
203201
expect(config.server.host).toBe('0.0.0.0')
@@ -210,7 +208,7 @@ describe('laravel-vite-plugin', () => {
210208
it('allows the Vite port to be configured when inside a Sail container', () => {
211209
process.env.LARAVEL_SAIL = '1'
212210
process.env.VITE_PORT = '1234'
213-
const plugin = laravel()
211+
const plugin = laravel('resources/js/app.js')
214212

215213
const config = plugin.config({}, { command: 'serve', mode: 'development' })
216214
expect(config.server.host).toBe('0.0.0.0')

0 commit comments

Comments
 (0)