-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Help with integration for Laravel Breeze Starter Kit #2
Comments
Looks like the problem is in your vite.config.js file: import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
],
/* ADDED: */
server: {
https: true,
hmr : {
host: 'ddev-laravel-breeze-vite.ddev.site'
},
port: 3001
},
}); The "ADDED" section should instead be:
This is because the main point of ddev-viteserve is to let Vite operate behind DDEV's routers. Default settings for my add-on expect the vite server to put out http on port 3000. DDEV's router will handle wrapping the output in https and translating the port to 3001. I'll likely update the docs soon to make this more clear; I'm also working on an extension to how the configuration works for DDEV generally with config.*.yaml files; once that fix lands, I'll take advantage of the new DDEV configuration feature to make my add-on more readily and intuitively configurable. |
Thanks very much for your fast reply! I tested some variations, A) server: {
https: true,
hmr : {
host: 'ddev-laravel-breeze-vite.ddev.site'
},
port: 3000
}, Opening https://ddev-laravel-breeze-vite.ddev.site/login returns: This site can’t provide a secure connectionddev-laravel-breeze-vite.ddev.site sent an invalid response. ERR_SSL_PROTOCOL_ERROR B) server: {
/* https: true,*/
hmr : {
host: 'ddev-laravel-breeze-vite.ddev.site'
},
port: 3000
}, Opening https://ddev-laravel-breeze-vite.ddev.site/login returns: Mixed Content: The page at 'https://ddev-laravel-breeze-vite.ddev.site/login' was loaded over HTTPS, but requested an insecure script 'http://ddev-laravel-breeze-vite.ddev.site:3000/@vite/client'. This request has been blocked; the content must be served over HTTPS. But the good news: C) server: {
/* https: true,*/
hmr : {
host: 'ddev-laravel-breeze-vite.ddev.site'
},
port: 3000
}, and opening up http://ddev-laravel-breeze-vite.ddev.site/login without But... is there a way to make this work via https as well? 🤔 |
This one can't work, for two reasons.
True. The add-on exports HTTP on 3000, and HTTPS on 3001, as I said above.
Closer, but still not right: you don't want to
Yep. Omit the This really is all the settings you need: import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
],
}); since using the defaults here actually will server you HTTP on 3000 and HTTPS on 3001 with the correct certificates without you doing any additional configuration. |
I've updated the README for release 0.1.1 to help make this more clear. I'm waiting on a new feature in DDEV to land before updating the README much more, since configuration will be a lot easier for people to do once I have access to |
Hey, thanks again for your support! Your recommended setup import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
],
}); results in the following generated HTML: <script type="module" src="http://[::]:3000/@vite/client"></script><link rel="stylesheet" href="http://[::]:3000/resources/css/app.css" /><script type="module" src="http://[::]:3000/resources/js/app.js"></script> </head> Which results in: Unfortunately I don't know all the details yet, but for me it seems to be the case that Laravels integration of vite depends on the Code references: |
PS: Just found a tutorial for a similar use case (Local Valet Server) which uses hmr{} and also adds support for certificates https://freek.dev/2276-making-vite-and-valet-play-nice-together |
You don't want to add certs, but rather have ddev-router be in charge of TLS termination in all cases. |
Thanks @rfay, I'll withdraw certificates from this discussion for now! :-D Further technical investigation: The
The With Official docs for vites
|
Forgot to mention the most important thing ;-) The <!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js']) And sorry in advance if I'm totally on the wrong track with hmr ;-) |
:-) What does the blade tag <!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js']) resolve to in the actual HTML generated and passed to the browser? It would need to either use the full path with the full URL using the host name used in DDEV generated certs, or a relative URI starting in "/", so that you inherit the correct protocol://HOST_NAME from the document. Anything else would be a problem. I don't know the internals of the Laravel Vite integration. I've written an integration for Golang, which should work in a similar way; I just generate golang template functions that resolve to tags. I know that I use the relative URI approach. Not sure what the Larvel's integration does, but we should be able to accommodate whatever it does do. |
<script type="module" src="http://127.0.0.1:3000/@vite/client"></script>
<link
rel="stylesheet"
href="http://127.0.0.1:3000/resources/css/app.css"
>
<script
type="module"
src="http://127.0.0.1:3000/resources/js/app.js"
></script>
<link
rel="icon"
type="image/x-icon"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAHZJREFUOE/t08ENgDAIBdD/6XjO4Jhup2CIMVXaao3xZq/AS4HAYZxmvHjcARGklqOKpRU7AaQUeaYKEGghFcAOCOEAhTCzKtINuFpDMkAkirdQ/iD2pZZncgvEYm/pARDLt5n8wPczuL6syy30HmV1jb3FMW8FYduDoVoaPbwAAAAASUVORK5CYII="
> |
@tyler36 Where does Laravel Vite get its notion of what the src is for that script tag? How is it set? Assuming that you're getting served HTTPS at MY-DDEV-SECURE-HOST:someport, we'd want src to be:
if we are using the add-on with its default settings. How would we get the Laravel integration to do that? Where is it getting the setting? |
See comment above, I quickly checked, that seems to be a configureServer(server) {
const hotFile = path.join(pluginConfig.publicDirectory, 'hot')
const envDir = resolvedConfig.envDir || process.cwd()
const appUrl = loadEnv('', envDir, 'APP_URL').APP_URL
server.httpServer?.once('listening', () => {
const address = server.httpServer?.address()
const isAddressInfo = (x: string|AddressInfo|null|undefined): x is AddressInfo => typeof x === 'object'
if (isAddressInfo(address)) {
viteDevServerUrl = resolveDevServerUrl(address, server.config)
fs.writeFileSync(hotFile, viteDevServerUrl)
setTimeout(() => {
server.config.logger.info(colors.red(`\n Laravel ${laravelVersion()} `))
server.config.logger.info(`\n > APP_URL: ` + colors.cyan(appUrl))
})
}
})
//...
/**
* Resolve the dev server URL from the server address and configuration.
*/
function resolveDevServerUrl(address: AddressInfo, config: ResolvedConfig): DevServerUrl {
const configHmrProtocol = typeof config.server.hmr === 'object' ? config.server.hmr.protocol : null
const clientProtocol = configHmrProtocol ? (configHmrProtocol === 'wss' ? 'https' : 'http') : null
const serverProtocol = config.server.https ? 'https' : 'http'
const protocol = clientProtocol ?? serverProtocol
const configHmrHost = typeof config.server.hmr === 'object' ? config.server.hmr.host : null
const configHost = typeof config.server.host === 'string' ? config.server.host : null
const serverAddress = address.family === 'IPv6' ? `[${address.address}]` : address.address
const host = configHmrHost ?? configHost ?? serverAddress
return `${protocol}://${host}:${address.port}`
} |
But according to that,
But it returns |
How is Laravel Vite configured? I find it unlikely that it's getting settings out of vite.config.js, for the same reason I don't do it in golang: parsing that file is not something you want to do if you're not using nodejs. THERE HAS TO BE SOME OTHER PLACE LARAVEL VITE IS GETTING ITS SETTINGS. And those are the settings you need to change, NOT vite.config.js. This is a good question for Enzo Innocenzi, but a quick look at the docs shows that there is indeed a place for these configurations. Short version: the dev-server configuration needs to tell Laravel Vite how to create the tags. I'm not sure exactly how vite.php is being used, so you'll need to explain that vite is running inside a docker container and that it is routed out to the host. Not sure exactly what the settings would be, but likely that is the place to get this configured. |
Has some information about changing host, certificates and using with Lagoon, Laravel Sails |
Whoops, I should have made this more clearer and do a better research before: I'm trying to use the brand new core integration of vite in Laravel. This is not the third party plugin https://laravel-vite.dev/ by Enzo Innocenzi anymore. It is instead in References: |
Still, it's substantially based on Enzo's work. Looked at the docs for the official integration; this is in fact this case, also as Enzo explains it on the Vite dev discord. I've left a long note explaining what we're trying to do for Enzo, asking who is best suited to answer the question. My sense is that Enzo may well be able to, since the official integration owes so much to his previous work. |
Thanks, very much appreciated! (Already learned a lot about Laravel & Vite as well here in this issue 👍 ) |
Here's what I hear from Enzo:
|
So... if you guys will try out using dev_url in vite.php, and see if it (1) creates the right tag in the browser and (2) actually works, we'll see where this goes. |
Thanks very much for working on this together! Maybe we should split our efforts at this point? 🤔 A) My goal is to use the official (new) vite implementation in laravel/framework + laravel-vite-plugin with DDEV. Demo DDEV repository to play around: https://github.com/mandrasch/ddev-laravel-breeze-vite/ Enzo Innocenzi just confirmed in vite Discord that Laravels new implementation does not have a But I guess the NodeJS source code of laravel-vite-plugin could be changed to read something like B) We could try to get innocenzi/laravel-vite working with DDEV and ddev-vite-serve. |
I'm not that familiar with the Laravel project, so I don't know how easy / how hard it is to get feature changes. But I encourage you to file an issue on the Laravel project with your use case. I did notice a feature where you can substitute your own code to render out the blade tag. This might be your best approach, since you'd be able to read DDEV environment variables w/o causing side effects. |
Here's what I was thinking about. I'd try constructing the correct URL using the DDEV generated environment variables, largely ignoring whatever laravel is telling you :-) |
BTW -- if you're happy with where we are, feel free to close this issue if Github lets you do that. |
Thanks, also interesting approach! 👍 I just read in the Laravel Sail community (also a Docker tool), that they just overwrite I tried it with the following for
and a the import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
]
}); It renders out the script tag correctly and the first run works: <script type="module" src="https://ddev-laravel-breeze-vite.ddev.site:3001/@vite/client"> But the web socket tries to connect on 3000 instead of 3001: Also tried the following config, unfortunately no success. But it feels close?! 🤔
|
No, server.hmr is almost certainly wrong. A web socket will need to be routed out by the nginx router, inside of DDEV. So if you do that, the web socket will never get out of DDEV. Remember, the settings of vite.config.ts are seen entirely inside of ddev, before routing occurs. Everything seen by the browser is outside of DDEV, after routing. But the Laravel app, since it runs inside of DDEV, can see
The So you want Laravel to generate the tags as "https://$DDEV_HOSTNAME:3001". If the official Laravel Vite does not give you a vite.php setting, you'll need to do this substitution in these calls, something like this: // Overrides script tag generation
Vite::makeScriptTagsUsing(function (string $url, Chunk $chunk = null): string {
if (isset($_ENV['DDEV_HOSTNAME']) {
$url = sprintf('https://%s:3001', $_ENV['DDEV_HOSTNAME']);
}
return sprintf('<script type="module" src="%s" defer></script>', $url);
});
// Overrides style tag generation
Vite::makeStyleTagsUsing(function (string $url, Chunk $chunk = null): string {
if (isset($_ENV['DDEV_HOSTNAME']) {
$url = sprintf('https://%s:3001', $_ENV['DDEV_HOSTNAME']);
}
return sprintf('<link rel="stylesheet" href="%s" crossorigin="anonymous" />', $url);
}); calling them where the docs say you should. This will change your URLs w/o side effects, I think. Once I have a place to set the default values of vite-port-inside-ddev and vite-port-outside-ddev, you'd use those as well. |
Thanks for your help! Can't quite get my head around all this. Good news (http): When I use https: I think I misunderstood that https:// isn't currently working out of the box with ddev-vite-serve? I already achieved overwriting the @Vite tag via But now the error were within vites Therefore I edited the hmr settings to change this, which seems to be the wrong approach as you pointed out. I'll fiddle around with that and get a better understanding. If you find time in future (or someone else reading this), a HTTPS-demo repository would be really appreciated! |
Closing this to not show it as open in your repo, but happy to discuss it further in here. Thanks very much for taking the time! |
The router also proxies out that internal 3000/HTTP out as 3001/HTTPS external. |
I'm unfortunately not deeply familiar with DDEV router. But DDEV docs state
So is this a DDEV router issue? Would opening the site via |
You potentially could; but you have to route HTTP to somewhere from what @rfay tells me, or the router won't work right. This is, um, a FEATURE of the router. But you certainly could switch the HTTP and HTTPS ports if you wish; easy to do by changing the DDEV env variables HTTPS_EXPOSE and HTTP_EXPOSE (see config.yaml), making external HTTPS 3000, and external HTTP 3001, for example. But I'm going to wait to config update I've been working on with Randy. |
This is all about what all reverse proxies do... all over the world. They typically route traffic from one entrypoint to a back-end HTTP server. And they often also terminate https. Because https traffic is encrypted, the back-end servers can't be serving https, because the reverse proxy (ddev-router in this case) can't decrypt it. And even if it did, it would mean two separate encryption/decryption processes and two separate sets of keys. Quite a mess. So ddev-router and every other reverse proxy in its class do https on the edge, and talk http typically to back-end servers. vite in this case is the back-end server. I hope that helps understanding of what's going on here. |
Thanks very much @rfay for clarification! (And sorry for the noob questions!) So I guess this narrows it down to vite and use the reverse proxies + https? I saw that they were quite a few issues submitted regarding reverse proxies (and docker) in vites official repo, I'll try to dive into them: https://github.com/vitejs/vite/issues?q=reverse+proxy+ Some mention But for debugging this I think I'll have to take a step back and start with a blank vite instead of a Laravel Starterkit: I'll try to get a working DDEV https setup with a blank vite v2 and blank vite v3 first. (I still don't have an idea what the correct vite config for https + docker + reverse proxy is). If anyone has any working DDEV + vite + https example repository, please let me know 🙏 |
PS: Okay, Craft CMS devs to the rescue! Just saw https://nystudio107.com/docs/vite/#local-development-environment-setup --> "Using DDEV" (via craftquest) They use the following config, which worked for me in https 🥳🥳🥳 The vite config is the following, just as @torenware suggested all the time here ;-) (And it's same as server: {
host: '0.0.0.0',
port: 3000
} The docker-compose file differs: # Override the web container's standard HTTP_EXPOSE and HTTPS_EXPOSE services
# to expose port `3000` of DDEV's web container.
version: '3.6'
services:
web:
ports:
- '3000'
environment:
- HTTP_EXPOSE=${DDEV_ROUTER_HTTP_PORT}:80,${DDEV_MAILHOG_PORT}:8025,3001:3000
- HTTPS_EXPOSE=${DDEV_ROUTER_HTTPS_PORT}:80,${DDEV_MAILHOG_HTTPS_PORT}:8025,3000:3000 The downside of using
Therefore the above approach can be used on only one DDEV project at a time, the second project will say "port already in use" (if I understand the docs correctly). |
You just want I'll be happy to do a screenshare call with you and work with you on your project and explain what's going on here. Let me know if you'd like to and there's a convenient time. But if you're going to use |
Thanks so much for your offer, @rfay! But I do hope this won't be necessary anymore (and you can use your time in a better way. ) I just tried out another simple setup with vite3, a custom port (Hope I got it right this time. Funfact: Repo: mandrasch/vite-php-setup-ddev-test (Fork of andrefelipe/vite-php-setup) # ./ddev/docker-compose.vite.yaml
version: '3.6'
services:
web:
expose:
- '5133'
environment:
- HTTP_EXPOSE=${DDEV_ROUTER_HTTP_PORT}:80,${DDEV_MAILHOG_PORT}:8025,5134:5133
- HTTPS_EXPOSE=${DDEV_ROUTER_HTTPS_PORT}:80,${DDEV_MAILHOG_HTTPS_PORT}:8025,5133:5133 /* vite/vite.config.js */
server: {
// respond to all network requests
host: '0.0.0.0',
// "Set to true to exit if port is already in use, instead of automatically try the next available port."
strictPort: true,
port: 5133
}, So using the vite port in HTTPS_EXPOSE instead of HTTP_EXPOSE did the trick for If I switch it to the following - which is also used in https://github.com/torenware/ddev-viteserve/blob/b133b2dd70c4359190755625ebc8f4887d72a850/docker-compose.viteserve.yaml - I get the following error when I open my DDEV project with https (which is the DDEV default afaik?):
# not working for https://vite-php-setup-ddev-test.ddev.site
expose:
- '5133'
environment:
- HTTP_EXPOSE=${DDEV_ROUTER_HTTP_PORT}:80,${DDEV_MAILHOG_PORT}:8025,5133:5133
- HTTPS_EXPOSE=${DDEV_ROUTER_HTTPS_PORT}:80,${DDEV_MAILHOG_HTTPS_PORT}:8025,5134:5133 Needs some more testing with Laravel, vite2, etc. - but I won't share that here anymore. 😉 Thanks so much you all! 🙏 🙏 🙏 |
I got it working on a similar note but i used
...
server: {
hmr: {
protocol: 'wss',
host: 'example.ddev.site',
}
},
... and then run I dont know if this will conflict any websocket flow but it works for my usecase and wanted to share :-) |
Hey,
thanks so much for providing this!
Laravel officially switched to their own vite-integration for their starter kits (See https://laravel.com/docs/9.x/vite, they are using https://www.npmjs.com/package/laravel-vite-plugin and their
@vite
-tag in blade).I tried to use this plugin with the Laravel Breeze Starter Kit, but visiting https://ddev-laravel-breeze-vite.ddev.site:3001/@vite/client returns
Demo repo: https://github.com/mandrasch/ddev-laravel-breeze-vite
My installation commands: https://github.com/mandrasch/ddev-laravel-breeze-vite/blob/main/README.md#how-was-this-created
DDEV version: ddev version v1.19.3
OS: Mac OSX Big Sur 11.6.5, M1 chip
Is this an issue related to ddev-viteserve or a general DDEV issue?
Thanks very much in advance for any hints! 🙏
Best regards,
Matthias
The text was updated successfully, but these errors were encountered: