I have a Blade component that relies on some JavaScript, which I’ve put into a standalone module. The only place I need this script is when I’m using the component, so I’ve removed any mention of it from my main script file. This was working fine using the development server (npm run dev
.) However, when I compile my assets for production (npm run build
) I get an empty file generated.
How can I force Vite to build this script, even though it doesn’t seem to think it’s used?
/resources/js/mycomponent.js:
"use strict";
class MyComponent {
constructor(container) {
container.innerHTML = "<b>foo</b>";
}
}
export default MyComponent;
/resources/views/components/mycomponent.blade.php
<div id="{{ $id }}" class="mycomponent-container"></div>
@vite("resources/js/mycomponent.js")
<script type="module">
import MyComponent from "{{ Vite::asset('resources/js/mycomponent.js') }}";
let containerId = @json($id);
new MyComponent(document.getElementById(containerId));
</script>
/vite.config.js:
import laravel from 'laravel-vite-plugin';
import { globSync } from "glob";
export default defineConfig(({command, mode}) => {
return {
appType: "mpa",
plugins: [
laravel({
input: globSync(["resources/js/**/*.*", "resources/sass/app.scss"]),
refresh: true,
}),
],
build: {
rollupOptions: {output: {}},
chunkSizeWarningLimit: 800,
},
}
});
Output:
vite v5.3.3 building for production...
✓ 656 modules transformed.
Generated an empty chunk: "mycomponent".
public/build/manifest.json 12.48 kB │ gzip: 1.41 kB
public/build/assets/material-icons-kAwBdRge.woff2 128.35 kB
public/build/assets/app-CuNfWWBx.css 261.14 kB │ gzip: 36.93 kB
public/build/assets/mycomponent-l0sNRNKZ.js 0.00 kB │ gzip: 0.02 kB
I’ve ended up creating another script file that just calls the component constructor. This is messy when I have multiple components on the page, and required a check to be put in place to ensure the component hasn’t already been initialized.
/resources/js/mycomponent.js:
"use strict";
class MyComponent {
constructor(container) {
// ensure the component isn't repeatedly created
if (container.dataset.initialized) {
return;
}
container.dataset.initialized = 1;
container.innerHTML = "<b>foo</b>";
}
}
export default MyComponent;
/resources/js/mycomponent-caller.js:
import MyComponent from "./mycomponent.js";
document.querySelectorAll(".mycomponent-container").forEach(el => new MyComponent(el));
/resources/views/components/mycomponent.blade.php
<div id="{{ $id }}" class="mycomponent-container"></div>
@vite("resources/js/mycomponent-caller.js")
Not sure this is the best way to go about it. I was hoping for an option in vite.config.js
to target that specific file for forced rollup, but this seems to work.