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

Allow array of paths to the preprocessCss phase #1888

Merged
merged 1 commit into from
Nov 9, 2014

Conversation

tstirrat
Copy link
Contributor

@tstirrat tstirrat commented Sep 5, 2014

Allow a hash of files in outputPaths.app.css to be passed to the CSS preprocessor.

var app = new EmberApp({
    outputPaths: {
      app: {
        css: {
          'main': '/css/main.css',
          'theme/a': '/css/theme/a.css'
        }
      }
    }
  }
});
module.exports = app.toTree();

// app/styles/main.scss    -> dist/css/main.css
// app/styles/theme/a.scss -> dist/css/theme/a.css

Ensures backwards compatibility so that when no paths are configured; app/styles/app.scss will still be written to assets/<app name>.css

Closes #1656.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 5, 2014

Note: Due to the way the style plugin registry works, the only way to activate SASS in the tests was to "install" one of the following:

registry.add('css', 'broccoli-sass', ['scss', 'sass']);
registry.add('css', 'broccoli-ruby-sass', ['scss', 'sass']);

I chose to mock broccoli-sass in the text fixtures. If you prefer, to avoid confusion, I could probably make an ember addon that registers a new scss interpreter instead:

registry.add('css', 'super-sass', ['scss']);

.. and then the fixtures would contain node_modules/super-sass instead of broccoli-sass

Let me know if this is worth doing.

@MichaelVdheeren
Copy link

A good solution for #1656 and thus an alternative for #1816


return requireLocal(this.name).call(null, [tree], input, output, merge({}, this.options, options));
var trees = paths.map(function (file) {
var outputName = (file === 'app') ? _this.applicationName : file; // keep backwards compat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make this multiline please?

@rwjblue
Copy link
Member

rwjblue commented Sep 7, 2014

I left a couple of comments, but this looks good. Thank you for the tests (mocking in that fixture seems good to me for now).

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

I quite like the solution by @MichaelVdheeren in #1816, where it auto builds any non _ prefixed files. This is what is documented by SASS and how sprockets and the sass watch command operate.

The only downside for this is that you do not have specific control over exactly which files are built, and (for my specific needs) you cannot control which files are built under certain environments. e.g. I set a really tiny scss file to be built in test mode to save time and only one theme to be built in dev mode (because broccoli-ruby-sass is slowwww):

var themes = ['themes/a/theme'];

// use a much faster css in test mode
if (process.env.EMBER_ENV === 'test') {
  themes = ['tiny'];
}

if (process.env.EMBER_ENV === 'production') {
  themes = themes.concat([
    'themes/b/theme',
    'themes/c/theme',
    'themes/d/theme',
    'themes/e/theme',
    'themes/f/theme'
  ]);
}

// later:
  preprocessCss: {
    options: {
      paths: themes
    }
  },

I wonder if we could use a combination of this PR and #1816. Perhaps default to 'auto' mode, which builds all non partial scss files; and provide the option of passing an array of paths (or a glob pattern) to be more specific:

preprocessCss: {
  paths: 'auto' // default .. builds anything without a partial _* prefix
},

// or

preprocessCss: {
  paths: ['a', 'b', 'c']
}

This could work in a predictable way for most users, and allow explicit configuration for those who need more.

Ideally, we don't want to decide on one way too hastily and then have to introduce breaking changes later. So your thoughts are welcome.

Naturally, documentation is the key. I'm willing to write it, once we know what we are implementing.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

one thing to note is that if we do use an auto mode, if people forget to name their partials with the _ prefix, it could start to deteriorate their build performance without them realising why.

@MichaelVdheeren
Copy link

Build performance is indeed the biggest problem as I found that using #1816 results in slow builds when you have multiple sass files (in our case for different internet explorers) which import ie bootstrap sass.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

There's even more to it than just the amount of files you're building. The .sass-cache dir is completely ineffective because sass (ruby) uses the file's path in the key for the cache. each time you run ember build the broccoli temp trees have new names, thus no cache. This is likely also the case for broccoli-sass (node-sass)..

I'm brainstorming ideas on how to get the sass cache to actually work.

It seems selectively including files is the way to go, until there are some perf improvements on broccoli-rub-sass (or node-sass can build extended selectors )

We can always add the auto option at a later date.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

@rwjblue I've updated the code based on your comments, let me know if there's anything else.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

one last thing. should we use files: [] instead of paths: []? Looking through ember-cli, I'm thinking that files might be the most consistent.

var trees = paths.map(function (file) {
var outputName = file;
if (file === 'app') {
outputName = _this.applicationName; // keep backwards compat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be updated per recent changes app.options.outputPaths.css specifically.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

@rwjblue rebased and updated to work with the outputPaths change. Tests passing. @jayphelps perhaps you can have a quick look, too.

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 7, 2014

Yeah, I think it makes sense to combine them.

My first inclination is that configuring the "inputs" inside your outputPaths hash feels a little strange. I tried a few other variations and most of them felt worse. The best I can find is if we change outputPaths to paths:

var app = new EmberApp({
    paths: {
      app: {
        css: {
          'main': '/css/main.css',
          'theme/a': '/css/theme/a.css'
        },
        js: '/js/app.js'
      },
      vendor: {
        css: '/css/vendor.css',
        js: '/js/vendor.js'
      },
      testSupport: {
        css: '/css/test-support.css',
        js: '/js/test-support.js'
      }
    }
});

@jayphelps
Copy link
Member

@tstirrat LGTM... (except this.name is undefined there btw...I think?)

@rwjblue will prolly have an opinion 🍭

The more I thought about it, the more I think we should stick as close to existing conventions as possible, the most prominent being indeed being grunt. For reference, there are many variations supported by grunt itself, most of which you can see here. We may want to at least consider utilizing the same code that grunt uses under the hood.

@bcardarella
Copy link
Contributor

Needs a rebase

@tstirrat
Copy link
Contributor Author

tstirrat commented Sep 8, 2014

I'm happy to go with the merging into outputPaths. I will sort it out this evening.

@tstirrat
Copy link
Contributor Author

I'm still working on this, just really busy at work this week. I'll get a chance over the weekend to finish it.

@tstirrat
Copy link
Contributor Author

I'm working towards this API, as suggested by @jayphelps :

var app = new EmberApp({
  outputPaths: {
    app: {
      css: {
        'main': '/css/main.css',
        'theme/a': '/css/theme/alpha.css'
      }
    }
  }
});

Output paths/filenames will be respected regardless of whether you are using a preprocessor or not.

@jayphelps
Copy link
Member

UNACCEPTABLE

@rwjblue
Copy link
Member

rwjblue commented Sep 17, 2014

Any updates here?

@tstirrat
Copy link
Contributor Author

made some progress but havent had time to diagnose some failing tests.

@tstirrat
Copy link
Contributor Author

It seems there is some trickery required in merging options below the first level:

// defaults in ember-app.js
{
    es3Safe: true,
    wrapInEval: !isProduction,
    outputPaths: {
      app: {
        css: {
          'app': '/assets/' + this.name + '.css'
        },
        js: '/assets/' + this.name + '.js' // <--- note this
      },
      vendor: {
        css: '/assets/vendor.css',
        js: '/assets/vendor.js'
      },
      testSupport: {
        css: '/assets/test-support.css',
        js: '/assets/test-support.js'
      }
    },
    // snip
}

// user's Brocfile.js
var app  = new EmberApp({
  outputPaths: {
    app: {
      css: {
        'main': '/css/main.css',
        'theme/a': '/css/theme/a.css'
      }
      // note: no 'js' key here
    }
  }
});

// merged options:

{
  outputPaths: {
    app: { 
      css: {
        'main': '/css/main.css',
        'theme/a': '/css/theme/a.css'
      }
    },
    vendor: {
      css: '/assets/vendor.css',
      js: '/assets/vendor.js'
    },
    testSupport: {
      css: '/assets/test-support.css',
      js: '/assets/test-support.js'
    }
  }
}

In this situation, the user would not expect to have to supply the outputPaths.app.js path unless they were changing it.

@rwjblue Given that a deep merge will also give undesired results (it will merge the default outputPaths.css.app key back in), we might need a custom merging method. Would you be ok with that?

I'd prefer not to change the options merging stuff, or start a new pattern, without consulting you.

@tstirrat
Copy link
Contributor Author

Once we have a correct options merging, this is ready to go from my end

@tstirrat
Copy link
Contributor Author

@rwjblue I've fixed the options merging issue - with failing test - and rebased. I think this is ready to go.

@stefanpenner
Copy link
Contributor

sorry for letting this linger, it unfortunately no longer merges cleanly

@tstirrat
Copy link
Contributor Author

tstirrat commented Nov 9, 2014

@stefanpenner I will rebase

@stefanpenner
Copy link
Contributor

@tstirrat :)

@stefanpenner
Copy link
Contributor

this appears to not be a breaking change can you confirm?

@tstirrat
Copy link
Contributor Author

tstirrat commented Nov 9, 2014

I wrote tests to keep backward compatibility:

  • without any preprocessors, all CSS files in app/styles/ are copied to the /assets path. (I believe this changed in 0.1.1, but was reverted in 0.1.2?)
  • app.css is renamed to <app-name>.css be default (unless you configure outputPaths)
  • with a preprocessor and no custom outputPaths, only the app.scss file is passed through (it is also renamed to <app-name>.css)

Correct me if i am wrong, but this should maintain backwards compat.

@stefanpenner
Copy link
Contributor

@tstirrat yes it should, thanks :)

@tstirrat
Copy link
Contributor Author

tstirrat commented Nov 9, 2014

I'm not sure how it will interplay with addon styles. I might need some time to digest those changes.

@stefanpenner
Copy link
Contributor

@rwjblue could use your eye re: add ons here.

@tstirrat
Copy link
Contributor Author

tstirrat commented Nov 9, 2014

let me rebase, in doing that, i will probably have to make the appropriate changes to get the addon tests passing.

@tstirrat
Copy link
Contributor Author

tstirrat commented Nov 9, 2014

I've rebased, the tests pass in isolation .. but I get intermittent errors on seemingly random tests in brocfile-smoke-test-slow.js when running all the tests together..

version: 0.1.2-multiple-css-files-ada95fb9e3


Missing npm packages:
Package: ember-random-addon
  * Specified: latest
  * Installed: (not installed)

Run `npm install` to install missing dependencies.

This is an addon used in a totally different set of tests. which makes me think the default package.json is not being copied correctly in the fixtures.

- Ensure backwards compat for app.scss -> <app name>.css
@tstirrat
Copy link
Contributor Author

tstirrat commented Nov 9, 2014

... perhaps it's an OSX thing.

passing fine on travis: https://travis-ci.org/stefanpenner/ember-cli/builds/40491315

@stefanpenner @rwjblue please let me know if there's anything else I can do here.

stefanpenner added a commit that referenced this pull request Nov 9, 2014
Allow array of paths to the preprocessCss phase
@stefanpenner stefanpenner merged commit 8e9aeb4 into ember-cli:master Nov 9, 2014
@tstirrat tstirrat deleted the multiple-css-files branch November 10, 2014 00:34
tstirrat added a commit to tstirrat/ember-cli that referenced this pull request Nov 10, 2014
stefanpenner added a commit that referenced this pull request Nov 10, 2014
tstirrat added a commit to tstirrat/ember-cli that referenced this pull request Nov 10, 2014
tstirrat added a commit to tstirrat/ember-cli that referenced this pull request Nov 10, 2014
OpakAlex pushed a commit to OpakAlex/ember-cli that referenced this pull request Nov 18, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Proposal: Compile multiple sass files
6 participants