Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Laravel Mix #1868

Closed
5 of 6 tasks
Log1x opened this issue Apr 2, 2017 · 19 comments
Closed
5 of 6 tasks

Laravel Mix #1868

Log1x opened this issue Apr 2, 2017 · 19 comments

Comments

@Log1x
Copy link
Member

Log1x commented Apr 2, 2017

Submit a feature request or bug report

Feature Request

There has been a good amount of chatter behind the scenes on if Sage 9 should move to Laravel Mix.

I've heard it has its fair share of issues but most seem to be getting patched as they arise. Jeffery Way who built Laravel Mix has an incredible reputation and Mix once all the remaining bugs are kinked out will be quite awesome.

It allows the use of stylus, sass, less, vue, and more out of the box with ridiculously easy configuration.

I'd love some community and developer feedback on this. If it gains traction but none of the developers have the time to work on it, I'd be willing to work on it in a PR as well as update the Sage 9 docs.

Main things to take into consideration is doing an initial mix configuration that allows us to remap all the directories, and extend various plugins/modules like purifyCss to work in Sage's environment.

And of course, customizing the notification icon to show a roots icon instead. :)

@samrap
Copy link

samrap commented Apr 3, 2017

Laravel Mix is very new, and Sage 9 is already in Beta. The beta phase is generally for bug fixes after all features have been implemented. To rewrite Sage 9 to be built off of Mix at this point in the game would not make sense IMO, especially when there is nothing wrong with Sage 9 as it stands. What does Mix have to offer that Sage doesn't that is worth taking Sage 9 development back to Alpha? To me a fluent API for people who don't understand webpack is not worth killing what the Sage developers have worked so hard for, especially when it works beautifully. Many people, myself and company included, are anticipating the release of Sage 9 in the near future. Porting everything over to Mix just doesn't make sense to me.

While I'm a huge Laravel fan I do not think that it makes sense to drastically change Sage 9 for the sake of a shiny new package when Sage is so close to being ready.

@Log1x
Copy link
Member Author

Log1x commented Apr 3, 2017

I wouldn't entirely say it'd bring Sage 9 back to alpha by any means. Implementation of Laravel Mix is quite easy.

const mix = require('laravel-mix').mix;

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Sage application. By default, we are compiling the Sass file
 | for your application, as well as bundling up your JS files.
 |
 */

const assetsPath = 'assets';
const distPath   = './dist';
const publicPath = '/app/themes/sage';

mix.setPublicPath(distPath);
mix.setResourceRoot('../');

mix.browserSync({
  proxy: 'example.dev',
  files: [
    `${publicPath}/**/*.php`,
    `${assetsPath}/**/*.js`,
    `${assetsPath}/**/*.css`
  ]
});

mix.js(`${assetsPath}/scripts/main.js`, `${distPath}/scripts`);

mix.stylus(`${assetsPath}/styles/main.styl`, `${distPath}/styles`, {
  use: [
    require('lost-stylus')()
  ]
});

mix.options({
  postCss: [
    require('lost')(),
    require('rucksack-css')()
  ]
});

// Hash and version files in production.
if (mix.config.inProduction) {
  mix.version();
}

// Source maps when not in production.
if (!mix.config.inProduction) {
  mix.sourceMaps();
}

Here's a config I made in 5 minutes that compiles Stylus and adds two postCss packages.

I guess the main things it offers is easier configuration for projects using Vue and Stylus over jQuery and SASS. It also has better error reporting, cleaner notifications on successful builds, vastly less devDependencies for Sage it's self, and the ability to omit the assets/build folder entirely.

Here's the required devDependencies using Mix:

  "devDependencies": {
    "eslint": "^3.19.0",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-import": "^2.2.0",
    "laravel-mix": "^0.10.0",
    "rimraf": "^2.6.1",
    "webpack": "^2.3.3"
  },

For what it's worth though, my config above is not yet PERFECT for implementation into Sage. But it's "working" albeit a bit dirty.

Also worth nothing that my Stylus example above is a bit more than most would need. Here's an example of a Mix that is comparable to the configuration that currently ships with Sage 9:

mix.js(`${assetsPath}/scripts/main.js`, `${distPath}/scripts`)
   .sass(`${assetsPath}/styles/main.scss`, `${distPath}/styles`);

Remaining fixes would include:

  • Renaming assets.json to mix-manifest.json or overriding Mix's name scheme using Custom Webpack Configuration
  • Doesn't seem to be moving all of the images from assets/images/* to dist/images/* -- not sure why, but I've only been playing with it for the past 15 minutes after seeing your post.
  • Change blade path for purifyCss
  • Implement the cache busting that Sage 9 is currently using if we don't want to use ?ver which would be simple enough with a Custom Webpack Configuration.

@samrap
Copy link

samrap commented Apr 3, 2017

"vastly less devDependencies for Sage it's self" isn't really a good argument, considering this is the hard dependencies list for Mix:

"dependencies": {
    "autoprefixer": "^6.7.3",
    "babel-core": "^6.20.0",
    "babel-loader": "^6.2.9",
    "babel-preset-env": "^1.3.0",
    "browser-sync": "^2.18.7",
    "browser-sync-webpack-plugin": "^1.1.4",
    "chokidar": "^1.6.1",
    "clean-css": "^4.0.7",
    "concatenate": "0.0.2",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^3.1.3",
    "css-loader": "^0.14.5",
    "extract-text-webpack-plugin": "^2.0.0-rc.3",
    "file-loader": "^0.10.1",
    "friendly-errors-webpack-plugin": "^1.5.0",
    "html-loader": "^0.4.4",
    "img-loader": "^2.0.0",
    "less": "^2.7.1",
    "less-loader": "^2.2.3",
    "lodash": "^4.17.4",
    "md5": "^2.2.1",
    "mkdirp": "^0.5.1",
    "node-sass": "^4.0.0",
    "on-build-webpack": "^0.1.0",
    "path": "^0.12.7",
    "postcss-load-config": "^1.0.0",
    "postcss-loader": "^1.2.1",
    "resolve-url-loader": "^2.0.0",
    "sass-loader": "^6.0.0",
    "style-loader": "^0.13.1",
    "uglify-js": "^2.7.5",
    "vue-loader": "^11.1.3",
    "vue-template-compiler": "^2.0.0",
    "webpack": "~2.3.0",
    "webpack-chunk-hash": "^0.4.0",
    "webpack-dev-server": "^2.2.0",
    "webpack-merge": "^4.0.0",
    "webpack-notifier": "^1.4.1",
    "webpack-stats-plugin": "^0.1.4"
  },

This means Sage has to trust Mix to use the proper versions of these packages and keep everything up-to-date. While historically Jeffrey Way and the Laravel ecosystem have a great track record of doing so, the more abstracted Sage becomes from the libraries it uses the more likely you are to get into a dependency hell, especially in the NPM ecosystem (from my experience).

It also means that Sage's docs will have a link that says "go read Laravel Mix's documentation for how to configure half of our theme". Just doesn't seem right to me. As a developer who's thinking of trying Sage for the first time, if I went to Sage's website (without knowing Laravel) I'd think "Oh great, another thing to learn".

Let's not forget that Elixir, the predecessor to Mix, was around for a short amount of time before being ditched for Mix. I like the idea of using Mix, but I think for Sage 9 it isn't ready yet. We're so eager to use the shiniest new thing, but why not wait until Sage 10 is being thought about a year or two from now and see if Mix is even still a thing?

The only convincing argument I'm seeing is errors and build output, which I agree could be much better in Sage 9. Why don't we work on that instead of just implementing something entirely different?

@eshimischi
Copy link

Lavarel Mix has nothing to do with Sage, i guess. If you really want it, just make your own fork and use lavarel mix and everything you need. For example, i moved all the webpack/rollup files into a module and use it with extra options and etc Migrate-build-files

@Log1x
Copy link
Member Author

Log1x commented Apr 4, 2017

It looks like with the directory rebasing that was pushed by retlehs that this may be full circle pretty fast.

I'm guessing the plan is going to be to separate Sage 9s build scripts into their own repo and then allow the user to choose between them and Mix. Mix as of now has full support with the new sage 9 directory structure. Main thing I need to add is image minification and a mix.copy.

I'll continue playing with this all when I get up tomorrow.

@zackkrida
Copy link

Long-time user, first-time commenter.

I think laravel mix is already pretty reliable and straight-forward. It's a light layer over Webpack.

Frankly, in the past Sage's build processes (whether the lest-than-speedy gulp builds of the past or the more modern varieties), have felt a bit slow and clunky. I think the root's team's time could be better spent on other things and abstracting the build process to mix seems like a great idea.

It also depends on the trajectory of the project. If the theme is about bringing together that great controller class, blade templates, and other external libs under a clean, well-organized theme structure, than switching to mix makes quite a bit of sense to me.

@samburgers
Copy link

Mix please.

@mAAdhaTTah
Copy link

I'm using mix on a Laravel project I just joined, and the Laravel mix wrapper over webpack is still using a beta version of webpack (2.2.0-beta28 IIRC). Webpack is at like 2.5.0+ currently, so unless you like being locked in to old versions of your dependencies, I would not recommend switching to Mix.

Long-term, we'll almost certainly be dropping mix in favor of using webpack directly.

@LeoColomb
Copy link
Contributor

LeoColomb commented May 10, 2017

Laravel mix wrapper over webpack is still using a beta version of webpack (2.2.0-beta28 IIRC)

Are you sure? 😄

At the opposite, I think using mix will simplify the non-php-dependencies management for Sage.

@mAAdhaTTah
Copy link

@LeoColomb That's fairly recent, it's locking to the 2.3.0 series instead of 2.50 (where they're at now) and it still highlights the type of issue you're going to run into depending upon a wrapper over webpack and other libraries instead of those libraries themselves.

@samburgers
Copy link

Another reason to use mix that is appealing, to me at least, is that mix supports the vue loader out of the box, which is a bit of a headache to setup otherwise.

@pix2D
Copy link

pix2D commented Jun 29, 2017

Mix is now past 1.0 and uses Webpack 3 as well.

I think the argument "go read Laravel Mix's documentation for how to configure half of our theme" doesn't really hold ground when Blade is already used so that's already the case anyway.

@Log1x
Copy link
Member Author

Log1x commented Jun 29, 2017

I've been using Laravel Mix in place of Sage's default Webpack setup for the last couple projects and haven't had any issues whatsoever.

Here is my current webpack.mix.js:

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

const app       = 'app';
const resources = 'resources';
const assets    = `${resources}/assets`;
const dist      = 'dist';

mix.setPublicPath(dist);
mix.setResourceRoot('../');

// Browser Sync
mix.browserSync({
  host: 'localhost',
  proxy: 'https://example.dev',
  port: 3000,
  browser: ['firefox.exe'],

  files: [
    `${app}/**/*.php`,
    `${resources}/**/*.php`,
    `${dist}/**/*.css`,
    `${dist}/**/*.js`
  ]
});

// Stylus
mix.stylus(`${assets}/styles/wrapper.styl`, `${dist}/styles/main.css`)
   .stylus(`${assets}/styles/wordpress/editor.styl`, `${dist}/styles/editor.css`)
   .stylus(`${assets}/styles/wordpress/admin/wrapper.styl`, `${dist}/styles/admin.css`)
   .stylus(`${assets}/styles/wordpress/login/wrapper.styl`, `${dist}/styles/login.css`);

// Javascript
mix.autoload({
   jquery: ['$', 'window.jQuery', 'jQuery']
});

mix.js(`${assets}/scripts/main.js`, `${dist}/scripts`)
   .js(`${assets}/scripts/tinymce.js`, `${dist}/scripts`);

// Assets
mix.copy(`${assets}/fonts`, `${dist}/fonts`, false)
   .copy(`${assets}/images`, `${dist}/images`, false);

// PostCSS
mix.options({
  processCssUrls: false,
  postCss: [
    require('rucksack-css')()
  ]
});

// Source maps when not in production.
if (!mix.inProduction()) {
  mix.sourceMaps();
}

// Hash and version files in production.
if (mix.inProduction()) {
  mix.version();
}

The above configuration is being used with Stylus instead of Sass, but is very easily interchangeable. (i.e. simply change .stylus to .sass)

To make asset_path work, I simply changed the get function in JsonManifest.php to:

public function get($asset)
{
    if (!starts_with($asset, '/')) {
        $asset = "/{$asset}";
    }

    return isset($this->manifest[$asset]) ? $this->manifest[$asset] : $asset;
}

I haven't experienced any of the issues reported with Sage's default Webpack setup using this Mix configuration. BrowserSync, reloading, injecting, etc. all works perfectly.

Here's an example of my package.json:

"devDependencies": {
  "eslint": "^4.1.1",
  "eslint-loader": "^1.8.0",
  "eslint-plugin-import": "^2.6.1",
  "laravel-mix": "^1.0.7",
  "rimraf": "^2.6.1",
  "webpack": "^3.0.0"
}
  "scripts": {
    "build": "NODE_ENV=development webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "build:production": "NODE_ENV=production webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "start": "NODE_ENV=development webpack --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "clean": "yarn run clean:cache && yarn run clean:dist",
    "clean:cache": "rimraf resources/cache",
    "clean:dist": "rimraf dist",
    "lint": "eslint resources/assets/scripts",
    "test": "yarn run lint"
  }

My webpack.config.js could easily be shortened, the above is just configured for my use-case and to give an example of a more "advanced" configuration.

@ciromattia
Copy link
Contributor

What are exactly the bonus points in using Laravel Mix instead of webpack in the sage scenario where all the build scripts are already written?

@retlehs
Copy link
Member

retlehs commented Jun 30, 2017

laravel mix is still webpack

@Log1x
Copy link
Member Author

Log1x commented Jun 30, 2017

Updated my post above to use the latest dependencies and the new Laravel Mix syntax.

@cesasol
Copy link

cesasol commented Jul 4, 2017

Maybe this can exist as a custom config in the docs.

@QWp6t
Copy link
Member

QWp6t commented Jul 4, 2017

We can probably make room for this in https://github.com/roots/sage-installer

Feel free to start an issue there to discuss this further.

To be clear, sage-installer is a dependency of sage (see my latest PR). It runs automatically when you use composer create-project roots/sage.

@webberwang
Copy link

Doesn't make sense to maintain a separate build tool with Sage. +1 for Laravel Mix

@roots roots locked and limited conversation to collaborators Jun 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests