roots / sage

WordPress starter theme with Laravel Blade components and templates, Tailwind CSS, and a modern development workflow
https://roots.io/sage/
MIT License
12.74k stars 3.06k forks source link

Laravel Mix #1868

Closed Log1x closed 7 years ago

Log1x commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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:

samrap commented 7 years ago

"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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

Mix please.

mAAdhaTTah commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

laravel mix is still webpack

Log1x commented 7 years ago

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

cesasol commented 7 years ago

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

QWp6t commented 7 years ago

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 commented 6 years ago

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