I have my image upload functionality working in development, for which my environment is Laravel Sail. It is working in development, but not in production Laravel forge where it is throwing 'b is not a constructor," and "({default{}}) is not a constructor", depending on whether you're using chrome or firefox respectively, which should have similar-identical environments. Only thing I can think I did differently between them is that in production I used npm run dev in development and npm run build for production. For the application, I'm using Laravel, InertiaJS, and Vue3 and It looks like this:
Vue Form and Script:
<form enctype="multipart/form-data" class="mb-4 md:flex md:flex-wrap md:justify-between" action="/dashboard/pages/store"
method="post">>
<input type="hidden" name="_token" :value="csrfToken">
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest" for="title">Title </label>
<input class="border py-2 px-3 text-grey-darkest md:mr-2" type="text" name="title" id="title">
</div>
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest"
for="slug">Slug </label>
<input class="border py-2 px-3 text-grey-darkest md:mr-2" type="text" name="slug" id="slug">
</div>
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest"
for="slug">Status </label>
<select class="border py-2 px-3 text-grey-darkest md:mr-2" name="status" id="status">
<option value="published">Published</option>
<option value="draft">Draft</option>
</select>
</div>
<!-- Page Header Image -->
<div class="flex flex-col mb-4 md:w-1/2">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest"
for="slug">Page Header Image </label>
<input class="border py-2 px-3 text-grey-darkest md:mr-2" type="file" name="header_image" id="header_image">
</div>
<div class="flex flex-col mb-4 md:w-full">
<label class="mb-2 uppercase tracking-wide font-bold text-lg text-grey-darkest" for="content">Content </label>
<editor name="content" id="content" api-key='xxxxxxxxxxxxxxxx'
:init="{
plugins: [
'advlist autolink lists link image charmap print preview anchor',
'searchreplace visualblocks code fullscreen',
'insertdatetime media table contextmenu paste imagetools'
],
toolbar: 'insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image ',
image_title: true,
automatic_uploads: true,
file_picker_types: 'image',
images_upload_handler: function (blobInfo, success, failure) {
let data = new FormData();
data.append('file', blobInfo.blob(), blobInfo.filename());
axios.post('/dashboard/pages/upload-images', data)
.then(function (res) {
success(res.data.location);
})
.catch(function (err) {
failure('HTTP Error: ' + err.message);
});
}
}"/>
</div>
<div class="grid mb-4 md:w-full place-items-center">
<button class="bg-red-500 md:w-36 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
type="submit">
Create
</button>
</div>
</form>
Here's the error I'm getting. I don't even know how to get it into the console so I can debug it further:
This seems to have been an issue with @rollup/plugin-commonjs.
The vite documentation for migration notes that this is the biggest difference between dev and build, so I tried their alternative strategy for removing commonjs because esbuild converts CJS-only dependencies to ESM.
https://vitejs.dev/guide/migration.html#using-esbuild-deps-optimization-at-build-time
To do this, from my Laravel build, in app.js I had to declare my config as a const, then you can use optimizeDeps.disabled: false
(the default in v3 is disabled: 'build'). @rollup/plugin-commonjs can be removed by passing build.commonjsOptions: { include: [] }
For me, that left my app.js looking like this:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
const config = defineConfig({
plugins: [
laravel({
input: 'resources/js/app.js',
ssr: 'resources/js/ssr.js',
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
ssr: {
noExternal: ['@inertiajs/server'],
},
alias: {
src: '/src',
},
});
config.build = { ...config.build, include: [] };
config.optimizeDeps = { disabled: false };
export default config;