Skip to content
This repository has been archived by the owner on Jul 11, 2022. It is now read-only.

Support for vite configuration #360

Closed
rellafella opened this issue May 21, 2021 · 21 comments
Closed

Support for vite configuration #360

rellafella opened this issue May 21, 2021 · 21 comments
Labels
bug Something isn't working
Milestone

Comments

@rellafella
Copy link

Description

Working through Andrew Welsh's article about using Vite for local dev with Craft. I feel like this config is very close to working but have run into a CORS issue, but can't seem to figure out why.

There is a heap of information here, but please let me know if I have missed anything that you might need to reproduce.

Screen Shot 2021-05-21 at 10 53 12 pm

Current config

vite.config.js

import vue from '@vitejs/plugin-vue';
import ViteRestart from 'vite-plugin-restart';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import path from 'path';

// https://vitejs.dev/config/
export default ({ command }) => ({
  base: command === 'serve' ? '' : '/dist/',
  build: {
    manifest: true,
    outDir: './web/dist',
    rollupOptions: {
      input: {
        app: './src/js/app.js'
      },
      output: {
        sourcemap: true
      }
    }
  },
  plugins: [
    nodeResolve({
      moduleDirectories: [path.resolve('./node_modules')]
    }),
    ViteRestart({
      reload: ['./templates/**/*']
    }),
    vue()
  ],
  publicDir: './src/public',
  resolve: {
    alias: {
      '@': '/src'
    }
  },
  server: {
    host: '0.0.0.0'
  }
});

vite.php

<?php

use craft\helpers\App;

return [
    'useDevServer' => App::env('DEV_MODE'),

    'manifestPath' => '@webroot/dist/manifest.json',

    'devServerPublic' => App::env('VITE_DEV_SERVER_PUBLIC'),

    'serverPublic' => App::env('SITE_URL') . '/dist/',

    'errorEntry' => '/src/js/app.js',

    'cacheKeySuffix' => '',

    'devServerInternal' => App::env('VITE_DEV_SERVER_PUBLIC'),

    'checkDevServer' => true,
];

package.json

{
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "dependencies": {
    "vue": "^3.0.5",
    "vue-confetti": "^2.0.8"
  },
  "devDependencies": {
    "@rollup/plugin-node-resolve": "^13.0.0",
    "@vitejs/plugin-vue": "^1.2.2",
    "@vue/compiler-sfc": "^3.0.5",
    "autoprefixer": "^10.2.5",
    "postcss": "^8.2.12",
    "tailwindcss": "^2.1.2",
    "vite": "^2.3.2",
    "vite-plugin-restart": "0.0.2"
  }
}

relevent env vars

DEV_MODE=1
SITE_URL=http://liamrella.test
VITE_DEV_SERVER_PUBLIC=http://localhost:3000/
WEB_ROOT_PATH=/app/web (aliased as @webroot)

Steps to reproduce

  1. ssh into Nitro site container
  2. run npm run dev

Additional info

  • Nitro CLI: 2.0.8
  • Nitro gRPC: 2.0.8
  • Docker API: 1.41 (1.12 min)
  • Docker CLI: 1.41
  • Craft CMS: 3.6.15
  • Vite (Craft plugin): 1.0.5
@rellafella rellafella added the bug Something isn't working label May 21, 2021
@jasonmccallister
Copy link
Member

@rellafella when you access the site directly, can you inspect the headers in the network tab and provide the output?

@khalwat
Copy link

khalwat commented May 21, 2021

Maybe you'll find some hints here? https://nystudio107.com/docs/vite/#using-nitro

As for CORS, Vite by default:

https://vitejs.dev/config/#server-cors

Sets it up to allow access from any origin. So your error is a little puzzling.

This really shouldn't be any different than setup for webpack or Laravel mix or the like, so maybe this article will help out: https://andrewmeni.ch/blog/hot-module-reloading-with-laravel-mix-v6-and-craft-nitro-2

@rellafella
Copy link
Author

@rellafella when you access the site directly, can you inspect the headers in the network tab and provide the output?

Response headers (app.js)

HTTP/1.1 200 OK
Server: Caddy
Date: Fri, 21 May 2021 21:33:15 GMT
Content-Length: 0

As for CORS, Vite by default:

https://vitejs.dev/config/#server-cors

Sets it up to allow access from any origin. So your error is a little puzzling.

This is what has me puzzled too, I have tried playing around with the server.cors options too with no luck.

This really shouldn't be any different than setup for webpack or Laravel mix or the like, so maybe this article will help out: https://andrewmeni.ch/blog/hot-module-reloading-with-laravel-mix-v6-and-craft-nitro-2

I'll see how I go trying to incorporate Andrew Menich's dev server config from mix and let you know on here if there is anything different.

@rellafella
Copy link
Author

Update:
I got this setup with mix 6 as per Andrew Menich's article without any CORS errors. Can't seem to see any discernible difference between the configurations, apart from the obvious.

That was following almost an identical configuration, obviously leveraging Twigpack instead though. But still the same process of nitro ssh then npm run dev in there. Files were being served from http://loclahost:3000

So still a bit perplexed. I am getting many more headers from the webpackDevserver files compared to the Vite dev server.

Response headers (app.js)

HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Origin: *
Content-Encoding: gzip
Content-Type: application/javascript; charset=utf-8
Date: Sun, 23 May 2021 13:29:58 GMT
Etag: W/"109df7-nygZAVBgQ9ovmqYIQZEV2Bsx2nI"
Server: Caddy
Vary: Accept-Encoding
X-Powered-By: Express
Transfer-Encoding: chunked

@khalwat
Copy link

khalwat commented May 23, 2021

I think Vite might use a web socket for some of this -- not sure how that'd impact anything tho.

@rellafella
Copy link
Author

I am not really sure what to do with this information but it might be useful to the issue.

In Andrew M's article he recommends using curl to debug the location of the webpack manifest so out of interest I thought I would try a similar thing with Vite.

If I run curl -I 'http://localhost:3000/src/js/app.js' I am getting a bunch of headers that are not present in the browser. Including Access-Control-Allow-Origin: *

/app $ curl -I 'http://localhost:3000/src/js/app.js'
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/javascript
Content-Length: 351
Last-Modified: Mon, 24 May 2021 02:23:33 GMT
ETag: W/"351-1621823013222"
Cache-Control: no-cache
Date: Mon, 24 May 2021 02:36:43 GMT
Connection: keep-alive
Keep-Alive: timeout=5

@khalwat
Copy link

khalwat commented May 24, 2021

@rellafella set:

    'checkDevServer' => false,

I'm pretty sure that what's happening is since you have that on, it's testing:

    'devServerInternal' => App::env('VITE_DEV_SERVER_PUBLIC'),

...to see if the Vite dev server is running. Since you have it set to:

VITE_DEV_SERVER_PUBLIC=http://localhost:3000/

...this is going to fail, because it's doing this inside of the Docker network. The address in there will not be the same as the VITE_DEV_SERVER_PUBLIC address. It'll be an internal Docker networking address.

So turn off checkDevServer until you're able to determine the internal Nitro network address for devServerInternal

For my Docker setup for example, it looks like this:

# Vite settings
VITE_DEV_SERVER_PUBLIC=http://localhost:3000/
VITE_DEV_SERVER_INTERNAL=http://vite:3000/

@rellafella
Copy link
Author

Have tried toggling checkDevServer but it doesn't seem to have any effect.

@khalwat
Copy link

khalwat commented May 24, 2021

It definitely will have an effect... if you tell it to check for the dev server, and it can't connect to it, it will fall back on the production build.

@rellafella
Copy link
Author

Sorry, yes in that respect it does have an effect, but it doesn't seem to change anything for the CORS issue.

I have tried a few different values for devServerInternal but it seems as though "http://localhost:3000" is the only one that will resolve if I try pinging it while the dev server is running.

@andrewmenich
Copy link

andrewmenich commented Jun 3, 2021

I've been summoned!

I was able to get HMR working with Nitro and Vite. Below is the config settings @rellafella posted, modified to match what has worked for me:

vite.config.js

import vue from '@vitejs/plugin-vue';
import ViteRestart from 'vite-plugin-restart';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import path from 'path';

// https://vitejs.dev/config/
export default ({ command }) => ({
  base: command === 'serve' ? '' : '/dist/',
  build: {
    manifest: true,
    outDir: './web/dist',
    rollupOptions: {
      input: {
        app: './src/js/app.js'
      },
      output: {
        sourcemap: true
      }
    }
  },
  plugins: [
    nodeResolve({
      moduleDirectories: [path.resolve('./node_modules')]
    }),
    ViteRestart({
      reload: ['./templates/**/*']
    }),
    vue()
  ],
  publicDir: './src/public',
  resolve: {
    alias: {
      '@': '/src'
    }
  },
  server: {
+    host: '0.0.0.0',
+    hmr: {
+        host: 'liamrella.test', // you could make this an ENV var
+        port: '3000',
+        path: '/'
+    }
  }
});

vite.php

<?php

use craft\helpers\App;

return [
    'useDevServer' => App::env('DEV_MODE'),

    'manifestPath' => '@webroot/dist/manifest.json',

    'devServerPublic' => App::env('VITE_DEV_SERVER_PUBLIC'),

    'serverPublic' => App::env('SITE_URL') . '/dist/',

    'errorEntry' => '/src/js/app.js',

    'cacheKeySuffix' => '',

-    'devServerInternal' => App::env('VITE_DEV_SERVER_PUBLIC'),
+    'devServerInternal' => 'http://localhost:3000/',
    'checkDevServer' => true,
];

relevant env vars

DEV_MODE=1
SITE_URL=http://liamrella.test
- VITE_DEV_SERVER_PUBLIC=http://localhost:3000/
+ VITE_DEV_SERVER_PUBLIC=http://liamrella.test:3000/
WEB_ROOT_PATH=/app/web (aliased as @webroot)

Edit: This assumes you're running vite from within the Nitro container.

@khalwat
Copy link

khalwat commented Jun 3, 2021

@andrewmenich nice! And this is running Vite inside of Nitro yes?

@andrewmenich
Copy link

@andrewmenich nice! And this is running Vite inside of Nitro yes?

Yep! I just updated my original post to clarify.

@khalwat
Copy link

khalwat commented Jun 3, 2021

Fantastic. I'm praying you decide to write a blog on this :)

@andrewmenich
Copy link

I plan to! I've pinged a few folks on Discord with my findings to see if it works for them. Just trying to avoid the "but it works on my machine!" situation.

@rellafella
Copy link
Author

@andrewmenich I just tested it and it works! Thanks heaps!

@roberttolton
Copy link

roberttolton commented Jun 7, 2021

Unfortunately for my setup, despite following what's been said here, is still not working. The only way I could get rid of the CORS error was to put the Vite Server on a subdomain, like so (Otherwise the requests responded with a 502 ERROR):

hmr: {
  host: 'vite.roberttolton.test',
  port: '3000',
  path: '/',
},
VITE_DEV_SERVER_PUBLIC=http://vite.roberttolton.test:3000/

This solves the CORS issue, but my requests to http://vite.roberttolton.test:3000/js/app.ts are just met with a blank page. The HTTP response is a 200 OK, but no content data is included at all.

Edit: Correction, doesn't seem to solve the CORS issue, just the 502 ERROR when trying to load the script directly.

And just to confirm the 502 ERROR, ran from the host machine:

curl -I 'http://roberttolton.test:3000/src/js/app.ts'

HTTP/1.1 502 Bad Gateway
Server: Caddy
Date: Mon, 07 Jun 2021 12:42:48 GMT

vite.config.ts

import vue from '@vitejs/plugin-vue'
import legacy from '@vitejs/plugin-legacy'
import ViteRestart from 'vite-plugin-restart'
import {nodeResolve} from '@rollup/plugin-node-resolve'
// @ts-ignore
import path from 'path'

// @ts-ignore
export default ({command}) => ({
    base: command === 'serve' ? '' : '/dist/',
    build: {
        manifest: true,
        outDir: './cms/web/dist',
        rollupOptions: {
            input: {
                app: '/src/js/app.ts',
            },
            output: {
                sourcemap: true
            }
        }
    },
    plugins: [
        legacy({
            targets: ['defaults', 'not IE 11']
        }),
        nodeResolve({
            moduleDirectories: [
                path.resolve('./node_modules'),
            ],
        }),
        ViteRestart({
            reload: [
                './cms/templates/**/*',
            ]
        }),
        vue()
    ],
    publicDir: './src/public',
    resolve: {
        alias: {
            '@': '/src',
        },
    },
    server: {
        host: '0.0.0.0',
        hmr: {
            host: 'roberttolton.test',
            port: '3000',
            path: '/',
        },
        cors: true
    }
});

Any help would be much appreciated.

Update

So, the only way I have been able to get this to work, on top of what's suggested above, is to make sure of the following (it could be all, or a combination):

  • Craft cannot be installed in a sub-directory (like cms) with the Nitro path set to it
  • Do not use nitro npm run dev you must instead do nitro ssh, npm install and then npm run dev (if you have the Nitro path set to a cms folder like above, you'll notice that package.json isn't available to you, because you're scoped / mounted into the cms folder)
  • I moved vite.config.ts and other such files into the root of my project, not in a src folder (might not be needed)

The reason I had set Nitro's config path for the site to be the cms folder was because otherwise the craft commands couldn't find the craft file.

If anyone can make the cms sub-folder approach work, please let me know what your Nitro config and other configs are, I'm happy to be proved wrong!

@stuh
Copy link

stuh commented Jun 25, 2021

Thanks @andrewmenich for this, works a treat here when using http. Just wondering if anyone has managed to get it all going on https? I've tried the vite-plugin-mkcert however on 'npm run dev' within nitro, mkcert fails with Permission Denied, I suspect it doesn't work well with the Alpine distro.

@ademers
Copy link

ademers commented Jun 30, 2021

I have Vite working as expected in Nitro 2 when running npm run dev and npm run build from within Nitro (i.e after running nitro ssh).

Now I've installed the Critical CSS companion package https://github.com/nystudio107/rollup-plugin-critical and have it configured as follows in vite.config.js:

    critical({
        criticalUrl: 'http://craft-starter.nitro:8080/',
        criticalBase: './web/dist/criticalcss',
        criticalPages: [
            { uri: 'contact', template: 'contact' },
        ],
        criticalConfig: {
        },
    }),

When I run npm run build, all works as expected except for the generation of my contact_critical.min.css. I get this error which appears to be related to Puppeteer. Maybe an issue with Puppeteer + Alpine Linux?

Error: Failed to launch the browser process! spawn /app/node_modules/rollup-plugin-critical/node_modules/puppeteer/.local-chromium/linux-722234/chrome-linux/chrome ENOENT


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md

    at onClose (/app/node_modules/rollup-plugin-critical/node_modules/puppeteer/lib/Launcher.js:750:14)
    at ChildProcess.<anonymous> (/app/node_modules/rollup-plugin-critical/node_modules/puppeteer/lib/Launcher.js:741:65)
    at ChildProcess.emit (events.js:315:20)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
    at onErrorNT (internal/child_process.js:465:16)
    at processTicksAndRejections (internal/process/task_queues.js:80:21)
(node:288) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process! spawn /app/node_modules/rollup-plugin-critical/node_modules/puppeteer/.local-chromium/linux-722234/chrome-linux/chrome ENOENT


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md

    at onClose (/app/node_modules/rollup-plugin-critical/node_modules/puppeteer/lib/Launcher.js:750:14)
    at ChildProcess.<anonymous> (/app/node_modules/rollup-plugin-critical/node_modules/puppeteer/lib/Launcher.js:741:65)
    at ChildProcess.emit (events.js:315:20)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12)
    at onErrorNT (internal/child_process.js:465:16)
    at processTicksAndRejections (internal/process/task_queues.js:80:21)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:288) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:288) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Here's some info on running Puppeteer on Alpine: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine

Is there something I can do/need to change, or is it Nitro itself? Thanks!

@jasonmccallister jasonmccallister added this to the 3.0 milestone Aug 5, 2021
@angrybrad angrybrad mentioned this issue Aug 30, 2021
Closed
@acalvino4
Copy link

I've been playing around with trying to get this working with https, since it seems that mixed content errors are the only thing holding me back from a working dev server.

it seems that if you have certs, you can just point to them from your vite.config.js like so:

  server: {
    https: {
      key: fs.readFileSync('path/to/key.pem'),
      cert: fs.readFileSync('path/to/cert.pem'),
    },
  },

But we know that nitro already generates certs for the sites it serves ....... so I'm curious if anyone knows where those are stored / if we could just point to them from our vite config rather than using vite-plugin-mkcert which seems to have permissions issues?

@jasonmccallister
Copy link
Member

Hi, we are closing this issue as we have decided to retire Nitro, so no additional work will occur on this project. You can read the official blog post here https://craftcms.com/blog/retiring-craft-nitro. We appreciate everyones feedback and involvement and we look forward to refocusing our efforts on Cloud!

If you're looking for a new local development environment, we recommend DDEV and have a knowledge base article to help you with the transition: https://craftcms.com/knowledge-base/migrating-from-craft-nitro-to-ddev.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

8 participants