You need a plugin to copy files with vite: https://www.npmjs.com/package/vite-plugin-static-copy
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();
?
@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 ?
@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.
destis relative tobuild.outDir
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?
@mdram83 Hard to say without seeing the code. I use it for inertia, and it works as expected
import.meta.glob('./Pages/**/*.jsx')
@Sinnbeck , here's my setup (which doesn't work in production after running npm run build).
- 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();
-
My custom js scripts are stored in resources/js/library folder and subfolders.
-
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,
}),
],
});
- 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
}
}
- 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 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?
@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'
Just got finished setting it up, and I can indeed recreate your problem. I will let you know if I figure it out
@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...
@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 :)
Another solution.. Use the import for something.. This stops rollup from removing it
const modules = import.meta.glob('./library/**/*.js')
console.log(modules) //makes sure it does not remove it
@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
@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.