[ Using Laravel ^8.40 / Inertia JS / Vue ^3.2.11 / Laravel Mix ^6.0.31 ]
I'm working on a multi-tenant SaaS platform for publishing client websites where each tenant has one or many Projects, each with their own mix workflow. Each tenant project has it's own unique routes for that tenant's domain, instead of the same routes for each individual tenant, which is the reason why I'm configuring parallel mix workflows (one workflow per project). I'm finding it challenging to configure the output directory structure exactly the way I want it and I've tried to figure it out based on documentation available online but I definitely feel like I'm missing something and I'm running around in circles...
My Vue components and Sass styles are stored in resources/{js|scss}/projects/{tenant}/ (including the pages sub-directory as well), and I'd like for Laravel Mix to output all of the compiled JS/CSS files to public/projects/{tenant}/{js|css}/ and have the mix-manifest.json file output to public/projects/{tenant} and have all of the "chunk'ed" page components output to the same folder as the other JS files... I'm not quite accomplishing this though... I've tried all manner of option combinations, but haven't found the winning set.
My webpack file (the {tenant} here is p017):
const mix = require('laravel-mix');
const path = require('path');
mix
/* Setup */
.setPublicPath('public/projects/p017')
.disableNotifications()
.autoload({jquery: ['$', 'window.jQuery']})
.webpackConfig({
resolve: {
extensions: ['.js', '.json', '.vue', '.css', '.scss'],
alias: {
'@': path.resolve(__dirname, 'resources/js/'),
'~': path.resolve(__dirname, 'resources/scss/')
}
},
output: {
chunkFilename: 'projects/p017/js/[name].js?id=[chunkhash]'
},
devtool: 'inline-source-map'
})
.options({
postCss: [
require('postcss-import'),
require('tailwindcss')
],
processCssUrls: true,
cssNano: {
discardComments: {removeAll: true}
}
})
/* Scripts */
.js('resources/js/projects/p017/p017.js', 'projects/p017/js/app.js')
.vue({version: 3, extractStyles: 'projects/p017/css/vue.css'})
.extract('projects/p017/js/vendor.js')
/* Styles */
.sass('resources/scss/projects/p017/p017.scss', 'projects/p017/css/app.css')
/* Cleanup */
.sourceMaps()
.version();
This webpack file results in the following (undesired) directory structure (all under public):
projects/p017/projects/p017/css/app.css
projects/p017/projects/p017/css/vue.css
projects/p017/projects/p017/js/app.js
projects/p017/projects/p017/js/manifest.js
projects/p017/projects/p017/js/resources_js_projects_p017_pages_Home_vue.js
projects/p017/projects/p017/js/vendor.js
projects/p017/mix-manifest.json
...and this is the desired directory structure (notice mix-manifest.json shouldn't move)...
projects/p017/css/app.css
projects/p017/css/vue.css
projects/p017/js/app.js
projects/p017/js/manifest.js
projects/p017/js/resources_js_projects_p017_pages_Home_vue.js
projects/p017/js/vendor.js
projects/p017/mix-manifest.json
If I remove the .setPublicPath() line, then the mix-manifest.json file lands in the public directory and conflicts with other tenants and if I set the output path for .js(), .vue(), .extract(), and .sass(), to public/projects/{tenant}/{js|css}/... then mix outputs all the JS/CSS files as /{js|css}/... (dropping the projects/{tenant}) which doesn't resolve to where they actually went.
Possible questions/solutions:
Is there a way to customize the mix-manifest.json directory or even the filename itself so I can prevent tenant conflicts?
Or, can I prepend public/ to each of the output directories in .js(), .vue(), .extract(), and .sass() without Laravel Mix stripping the projects/{tenant} from the output path?
Or, am I missing a better / all-encompasing set of documentation that describes in greater detail how to accomplish this?