Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

PetroGromovo's avatar

How can I on Laravel 9 site with vite.config.js add custom js file?

In prior versions of Laravel, I moved code with custom js files into webpack.mix.js. Is there a way to make a similar one in Laravel 9, which uses vite.config.js

mix.copy('resources/js/custom-file.js', 'public/js/').version();

?

0 likes
15 replies
PetroGromovo's avatar

@Sinnbeck I added the package in the project and addded lines in vite.config.js :

import { viteStaticCopy } from 'vite-plugin-static-copy'
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [


        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),



        viteStaticCopy({
            targets: [
                {
                    src: 'resources/js/custom.js',
                    dest: 'js/custom.js'
                }
            ]
        })


    ],
});

I run command

npm run dev

without errors.

I created file resources/js/custom.js just with 1 line :

alert('custom.js')

I expected to have new file under /public/js subdirectory and alert message running the app, but it did not happen...

What is wrong ?

thinkverse's avatar

@PetroGromovo the dest should be the name of the destination folder, not the file name, relative to the build output directory. For instance, given the following target.

viteStaticCopy({
    targets: [{
        src: 'resources/js/custom.js',
        dest: 'js'
    }]
})

The output custom.js will be in the public/build/js directory, it even states it's relative to the build directory on their README.

dest is relative to build.outDir

mdram83's avatar

Is there a way to do it without installing a plugin?

I tried to follow import.meta.glob syntax: https://vitejs.dev/guide/features.html#multiple-patterns with goal to be able to import more than one scripts with single statement.

But whatever I will put in script address, my .js files are not later available in /build/manifest.json file (only app.js and app.css are available), like they were not included in npm run build.

I was able to include my custom .js files directly in vite.config.js: import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
                'resources/js/library/ajax/isbn-details.js',   // this line worked for me dunring build
            ],
            refresh: true,
        }),
    ],
});

but I would like to take advantage of import.meta.glob so I don't need to add each individual file.

Do you know what may be wrong with using import.meta.glob?

Sinnbeck's avatar

@mdram83 Hard to say without seeing the code. I use it for inertia, and it works as expected

 import.meta.glob('./Pages/**/*.jsx')
mdram83's avatar

@Sinnbeck , here's my setup (which doesn't work in production after running npm run build).

  1. In resources/js/app.js I have following lines (now I tried to copy sth. similar to your code, but still without a success):
import.meta.glob('./library/**/*.js');

import './bootstrap';

import Alpine from 'alpinejs';

window.Alpine = Alpine;

Alpine.start();
  1. My custom js scripts are stored in resources/js/library folder and subfolders.

  2. In my vite.config.js I have following content:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
                // 'resources/js/library/ajax/isbn-details.js', (THIS ONE COMMENTED TO CHECK IF IT WILL WORK JUST FROM app.js, BUT IT DOESN'T)
            ],
            refresh: true,
        }),
    ],
});
  1. This is how public/build/manifest.json looks after running npm run build in prod:
{
  "resources/js/app.js": {
    "file": "assets/app.16890906.js",
    "src": "resources/js/app.js",
    "isEntry": true
  },
  "resources/css/app.css": {
    "file": "assets/app.d4cf3d7d.css",
    "src": "resources/css/app.css",
    "isEntry": true
  }
}
  1. finally, this is how I try to call different .js files in blade component file (works in dev, not in prod, guess due to missing entry in manifest.json file):
@push('custom-scripts')
    @vite('resources/js/library/ajax/isbn-details.js')
@endpush

If it works for you, there is a chance I can still try with import.meta.glob.

Do you also use import.meta.glob in your app.js file or maybe somewhere else? Or maybe looking at this code fragments you could see any other issue that I miss?

Regards Michal

Sinnbeck's avatar

@mdram83 what about if you run npm run build locally? Thats a bit faster when debugging as well.

My app is react, so I use jsx, and I dont manually call any the files in @vite(), but they are inside my manifest.json. I cannot share it as its 4k lines long

mdram83's avatar

@Sinnbeck I tried to build locally but effect is the same (it still works on my local environment but files are missing in manifest.json).

Do you also call import.meta.glob in resources/js/app.js or maybe somewhere else? Not sure if that would make a difference but maybe there is some difference...

And for custom files that you import with import.meta.glob, do you use also plugin mentioned above ( https://www.npmjs.com/package/vite-plugin-static-copy) or are you able to work without it?

Sinnbeck's avatar

@mdram83 for images i just import them where I need them, otherwise I would use the import trick yes.

And chance that roll up detects that the file does nothing and skips it? Can you share a file? Or try adding something like this

window.foo = 'foo' 
Sinnbeck's avatar

Just got finished setting it up, and I can indeed recreate your problem. I will let you know if I figure it out

mdram83's avatar

@Sinnbeck I added your code line to one of .js file but still no success. Files actually define some window.foo = function() {... etc. but took your line just to be sure :)

I tried with this tip (https://stackoverflow.com/questions/73416067/how-to-make-laravel-vite-copy-static-assets-versioned-to-build-folder) to make sure it is not because of small files but that also didn't help for build process to add my custom .js files to manifest.json.

I tried with putting images in resources/images/ just to try it out and it actually works for images. But still import.meta.glob seems to ignore my .js files...

Sinnbeck's avatar

@mdram83 Ok got it sort of working.

import.meta.glob('./library/**/*.js', { as: 'raw' })

There might be another flag that is better, but this works it seems. Just be aware that it does not do a clean copy job. It will compile it :)

mdram83's avatar

@Sinnbeck I confirm using import for something solved by problem. Thank you so much for your help! Regards!

PS. No matter if I use { as: 'raw' } argument or not, I still have to use results for something (decided for console.log()) and then my .js files are included in manifest.json

Sinnbeck's avatar

@mdram83 I got mine working by setting raw, but the other solution is probably better. There might be some other way to tell rollup to leave it alone, but I don't know enough about it yet to say how.

Anyways. If it is solved please mark a best answer

Please or to participate in this conversation.