I have read quite a few "issues" (https://github.com/JeffreyWay/laravel-mix/issues/197 & https://github.com/JeffreyWay/laravel-mix/issues/488) on here and I would like to make a feature request to solve this.
I find it very useful to have multiple entry points / vendor file extractions, for use cases such as backend and frontend assets extraction.
Simple example
// Mix backend resources.
mix.js('resources/assets/backend/js/app.js', 'public/backend/js')
.extract(['vue', 'vuetify']);
// Mix frontend resources.
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['jquery', 'bootstrap']);
Currently (with Laravel Mix 1.2.0), the mix-manifest.json file would look like this:
{
"/backend/js/app.js": "/backend/js/app.js",
"/js/vendor.js": "/js/vendor.js",
"/js/app.js": "/js/app.js",
"/js/manifest.js": "/js/manifest.js",
}
The output should be as follows:
{
"/backend/js/vendor.js": "/backend/js/vendor.js",
"/backend/js/app.js": "/backend/js/app.js",
"/backend/js/manifest.js": "/backend/js/manifest.js",
"/js/vendor.js": "/js/vendor.js",
"/js/app.js": "/js/app.js",
"/js/manifest.js": "/js/manifest.js",
}
I would love to see this included, because in my case I actually even have 3 entry points. Haha
Any ideas?
Here is one way to achieve this right now - https://github.com/omnichronous/multimix
@Chinese1904 This was a feature built in already it was tagged in 0.12.0
https://github.com/JeffreyWay/laravel-mix/releases/tag/v0.12.0
https://github.com/JeffreyWay/laravel-mix/pull/609
seems like it dropped during the rewrite.
@VinceG Hi, I followed your instructions for separating mix generated files by project parts.
I made landing.mix, and left default webpack.mix for admin assets. And added commands like this comment to package.json.
But when I ran commands listed bellow, mix-manifest.js was rewrites per. Where I made mistake?
// Default command
"production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
// Added command
"landing-prod": "yarn run production -- --env.mixfile=landing.mix"
node -v -> v7.9.0
"laravel-mix": "^1.2.2"
Try with mix 0.9.2 seems like the code that handles that was removed in recent mix versions
Vincent Gabriel
Software Engineer
Please excuse my brevity, sent from my iPhone
On Jul 29, 2017, at 14:35, Airat notifications@github.com wrote:
@VinceG Hi, I followed your instructions for separating mix generated files by project parts.
I made landing.mix, and left default webpack.mix for admin assets. And added commands like this comment to package.json.
But when I ran commands listed bellow, mix-manifest.js was rewrites per. Where I made mistake?// Default command
"production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
// Added command
"landing-prod": "yarn run production -- --env.mixfile=landing.mix"
node -v -> v7.9.0
"laravel-mix": "^1.2.2"—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
@VinceG thanks for quick response.
I fixed my issue with this
Even using this solution I still have the problem that mix-manifest.json gets rewritten and I ends up with it according to the last build, either admin or website :(
Hi guys, it's 1.4.3 version available now. Does anyone know, was this issue fixed there?
@aziev I am certain it did not, but the multimix works well for me proposed by VinceG
It will be very helpful if we will can create multiple manifest files. This is my question that describes problem:
https://laracasts.com/discuss/channels/elixir/multi-vendor-files
@96andl I'm using laravel-multimix with this solution https://github.com/fandogh/laravel-multimix/issues/3#issuecomment-435842981
to create multiple manifest files.
On top of that, I use this blade directive:
Blade::directive('client_css', function ($expression) {
return "<?php echo mix('/css/' . str_replace(' ', '-', strtolower(config('client.name', 'app'))) . '.css', str_replace(' ', '-', strtolower(config('client.name', 'app')))) ?>";
});
and then use
<link href="@client_css()" rel="stylesheet">
in my layout file.
I hope this helps you in your endeavour :)
Hi ! I wrote a blog post on how to build multiple vendors using Laravel Mix. I think it's solving your issue :)
http://www.compulsivecoders.com/tech/how-to-build-multiple-vendors-using-laravel-mix/
Hope it helps!
@charlesBochet @Chris1904 At this point there is no need for that anymore. All you have to do is change the output folder and you'll have a mix-manifext.json file for each build. Then in laravel you just use mix('app.js', 'path/to/mix-manifest')
All of those packages and changes (including mine)are not longer required. This is also a safer approach since you only build what you need and not everything.
@VinceG I trust you, but what is exact solution as of now?
I wanted separate webpack.mix.js files to specify separate targets. If I try to specify it in one file like this:
mix.react('resources/assets/js/frontend/app-server.js', 'public/js/server')
.webpackConfig({ target: 'node' })
mix.react('resources/assets/js/frontend/app-client.js', 'public/js/client')
.webpackConfig({ target: 'web' })
Only one target is applied to both files, although they are in different folders and both are written to one manifest file
{
"/js/client/app-client.js": "/js/client/app-client.js",
"/js/server/app-server.js": "/js/server/app-server.js"
}
EDIT* I forgot to mention, that charlesBochet's solution (https://github.com/JeffreyWay/laravel-mix/issues/989#issuecomment-440756310) worked for me
@ievgenklymenko Just have two separate webpack.mix.js file.
package.json
"dev": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"server": "npm run dev -- --env.mixfile=server.mix",
"client": "npm run watch -- --env.mixfile=client.mix",
server.mix.js
let mix = require("laravel-mix");
let distPath = "public/js/server";
mix.react('resources/assets/js/frontend/app-server.js', distPath)
.webpackConfig({ target: 'node' })
.disableNotifications()
.sourceMaps()
.setPublicPath(distPath)
.setResourceRoot("/");
if (mix.inProduction()) {
mix.version();
}
client.mix.js
let mix = require("laravel-mix");
let distPath = "public/js/client";
mix.react('resources/assets/js/frontend/app-client.js', distPath)
.webpackConfig({ target: 'web' })
.disableNotifications()
.sourceMaps()
.setPublicPath(distPath)
.setResourceRoot("/");
if (mix.inProduction()) {
mix.version();
}
@VinceG works wonderfully, thank you!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@charlesBochet These lines in webpack.mix.js not working with yarn:
if (['app', 'landing'].includes(process.env.npm_config_section)) {
require(`${__dirname}/webpack.${process.env.npm_config_section}.mix.js`);
} else {
console.log(
'\x1b[41m%s\x1b[0m',
'Provide correct --section argument to build command: app, landing'
);
throw new Error('Provide correct --section argument to build command!');
}
I write:
yarn --section=landing run watch
And it shows me an error:
Provide correct --section argument to build command: app, landing
Also tried process.env.section without success.
My custom solution, based on Mix init file. 🙂
--config-name
package.json
{
"scripts": {
"build": "webpack",
}
}
webpack.config.js
const path = require('path')
const ComponentFactory = require('laravel-mix/src/components/ComponentFactory')
const WebpackConfig = require('laravel-mix/src/builder/WebpackConfig')
/**
* Export the configurations build for each assets target.
*
* @type {Promise<any[]>}
*
* @link https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations
*/
module.exports = Promise.all(['target-a', 'target-b'].map(async target => {
/**
* As our first step, global variables are build or
* reset with default value.
*/
global.File = require('laravel-mix/src/File')
global.Config = require('laravel-mix/src/config')()
global.Mix = new (require('laravel-mix/src/Mix'))()
/**
* We'll pull in the user's mix file.
* Based on what the user requests in that file,
* a generic config object will be constructed for us.
*/
new ComponentFactory().installAll()
require(path.join(__dirname, `webpack.${target}.mix`))
/**
* Just in case the user needs to hook into this point
* in the build process, we'll make an announcement.
*/
Mix.dispatch('init', Mix)
/**
* Now that we know which build tasks are required by the
* user, we can dynamically create a configuration object
* for Webpack. And that's all there is to it. Simple!
*/
const config = new WebpackConfig().build()
config.name = target
return config
}))
webpack.target-a.mix.js
Your isolated but standard mix file for target-a assets.
webpack.target-b.mix.js
Your isolated but standard mix file for target-b assets.
the option of extractVueStyles does not work when we use multiple (.js) for vue, it only takes the styles of the last one (.js) added
Hi ! I wrote a blog post on how to build multiple vendors using Laravel Mix. I think it's solving your issue :)
http://www.compulsivecoders.com/tech/how-to-build-multiple-vendors-using-laravel-mix/
Hope it helps!
@charlesBochet That's a superb approach! Thanks for that! (You can find my way of applying your approach in the above reference)
However, is there a way to make npm run watch-poll work with this approach?
Hi! I wrote a blog post on how to build multiple vendors using Laravel Mix. I think it's solving your issue :)
http://www.compulsivecoders.com/tech/how-to-build-multiple-vendors-using-laravel-mix/
Hope it helps!
@charlesBochet solution works perfect for me! Thank you!
Most helpful comment
@ievgenklymenko Just have two separate webpack.mix.js file.
package.json
server.mix.js
client.mix.js