When you look at the compiled app-main.js file, what does it contain?
Use more than one JS file in Vite
Hello,
I'm trying to insert a custom JS file that contains some helpers in my views with Blade.
I noticed that even apparently configuring everything correctly, I can't access constant variables or functions in that file.
Always give the error "Uncaught ReferenceError".
Follows the settings of my files.
vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/sass/app.scss',
'resources/js/app.js',
'resources/js/app-main.js',
],
refresh: true,
}),
],
});
app-main.js
const test = "ok!";
function my_test() {
console.log("Hello!");
}
File .blade
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- CSS/Scripts -->
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
<!-- Scripts -->
@vite(['resources/js/app-main.js'])
<script>
console.log(test);
console.log(my_test());
</script>
</body>
</html>
What could be wrong?
Laravel uses JavaScript modules, it doesn't attach functions, variables, constants, etc to the global context, it's isolated to each module or file. You can see this if you look at the source sent to your browser, you should see each <script> tag use type="module".
Given this, your inline JavaScript must also be a JavaScript module. But given Vite's asset bundling you have two options to access the modules using inline JavaScript.
Option 1
The first option is to add everything to the window object, which is great if you have other JavaScript libraries that need to access things from that object.
const test = "ok!";
function my_test() {
console.log("Hello!");
}
window.my_test = my_test;
window.test = test;
<script type="module">
console.log(test);
console.log(my_test());
</script>
Option 2
The second is to use export and import.
export const test = "ok!";
export function my_test() {
console.log("Hello!");
}
And then use Vite::asset in your inline JavaScript to import the parts you need.
<script type="module">
import { test, my_test } from '{{ Vite::asset('resources/js/app-main.js') }}';
console.log(test);
console.log(my_test());
</script>
Notice as I said before, you need to use <script type="module"> on your inline JavaScript for this to work.
Using the first option is the safest IMO given Vite's minifying and tree-shaking which removes pretty much anything that isn't used in files Vite sees, and it doesn't see your inline JavaScript, hence why your app-main.js is empty when running build.
There are ways to force Vite to not remove unused code, but I haven't found a way that's bulletproof, it's mostly hacky ways that break easily. 🤷♂️
Hope that helps you solve your issue.
Please or to participate in this conversation.