Tools: splitHtml doesn't split CSS

Created on 3 Sep 2016  路  13Comments  路  Source: Polymer/tools

Description

I added a task to my gulpfile to minify CSS with cssnano, the .css files get minified but the CSS code inside <style> tags inside elements don't get minified. It does work with javascript.

Versions & Environment

  • polymer-build: 0.4.1
  • node: 6.5.0
  • Operating System: Windows 10

    Steps to Reproduce

Run gulp using a gulpfile that contains this:

const polymerJSON = require(global.config.polymerJsonPath);
const project = new polymer.PolymerProject(polymerJSON);
const cssnano = require('gulp-cssnano');

function source(){
  return project.sources().pipe(project.splitHtml())
      .pipe(gulpif('**/*.css', cssnano()))
      .pipe(project.rejoinHtml());
}

I'm using generator-polymer-init-custom-build so the gulpfile is the same except I added the pipe that minifies CSS, the code above is just the part that you probably care about, but if you need any additional information let me know.

Here's a repo so you can see for yourself: https://github.com/raulsntos/polymer-build-test
See how the file style.css was minified (source | output) but the style inside my-app was not (source | output).

Expected Results

Split CSS code from HTML to minify it.

Actual Results

CSS inside HTML is not minified. Only CSS in .css files is minified.

build wontfix

Most helpful comment

There was a little more conversation in https://github.com/Polymer/polymer-build/pull/40, unfortunately it's not a completely trivial fix.

BUT while digging into this I realized that css-slam (the wc-ready library that we use to minify css) works on inline CSS as well. So even though we currently aren't extracting the CSS, you can still make the following change to get CSS minification to work on inlined styles:

var cssSlam = require('css-slam').gulp();

  .pipe(project.splitHtml())
  .pipe(gulpif(/\.js$/, uglify))
  .pipe(gulpif(/\.css$/, cssSlam))
+ .pipe(gulpif(/\.html$/, cssSlam))
  .pipe(gulpif(/\.html$/, htmlminify))
  .pipe(project.rejoinHtml())

We'll probably make this change in the CLI as a temporary fix until someone is able to work on true style splitting/joining.

All 13 comments

In polymer-project.ts (_transform method starting at line 297), it looks like nothing is being done with the style tags:

_transform(file:` File, encoding: string, callback: FileCB): void {
    let filePath = osPath.normalize(file.path);
    if (file.contents && filePath.endsWith('.html')) {
      try {
        let contents = file.contents.toString();
        let doc = dom5.parse(contents);
        let body = dom5.query(doc, pred.hasTagName('body'));
        let head = dom5.query(doc, pred.hasTagName('head'));
        let scriptTags = dom5.queryAll(doc, HtmlSplitter.isInlineScript);
        let styleTags = dom5.queryAll(doc, pred.hasTagName('style'));

        // let scripts = [];
        // let styles = [];

        for (let i = 0; i < scriptTags.length; i++) {
          let scriptTag = scriptTags[i];
          let source = dom5.getTextContent(scriptTag);
          let typeAtribute = dom5.getAttribute(scriptTag, 'type');
          let extension = typeAtribute && extensionsForType[typeAtribute] || 'js';
          let childFilename = `${osPath.basename(filePath)}_script_${i}.${extension}`;
          let childPath = osPath.join(osPath.dirname(filePath), childFilename);
          scriptTag.childNodes = [];
          dom5.setAttribute(scriptTag, 'src', childFilename);
          let scriptFile = new File({
            cwd: file.cwd,
            base: file.base,
            path: childPath,
            contents: new Buffer(source),
          });
          this._project.addSplitPath(filePath, childPath);
          this.push(scriptFile);
        }

        let splitContents = dom5.serialize(doc);
        let newFile = new File({
          cwd: file.cwd,
          base: file.base,
          path: filePath,
          contents: new Buffer(splitContents),
        });
        callback(null, newFile);
      } catch (e) {
        logger.error(e);
        callback(e, null);
      }
    } else {
      callback(null, file);
    }
  }

Additionally, the _rejoin method (starting on line 394) doesn't do anything with style tags either.

Your gulpfile looks good. It seems that splitting CSS just isn't implemented currently. I've just started a fork to implement it myself. Not sure if the polymer team has anyone on it, but I will create a pull request when I get something working.

@hurst thanks for looking into this, you're right I can't see any css-related splitting/rejoining code either 馃槙 I could have sworn we had this working at some point, maybe it got removed accidentally during a merge or refactoring.

@hurst would you be able to submit your fork in a PR? We'd all greatly appreciate it :)

:+1: status update?

Update: I am using gulp-posthtml with posthtml-postcss in order to accomplish the style processing.

There was a little more conversation in https://github.com/Polymer/polymer-build/pull/40, unfortunately it's not a completely trivial fix.

BUT while digging into this I realized that css-slam (the wc-ready library that we use to minify css) works on inline CSS as well. So even though we currently aren't extracting the CSS, you can still make the following change to get CSS minification to work on inlined styles:

var cssSlam = require('css-slam').gulp();

  .pipe(project.splitHtml())
  .pipe(gulpif(/\.js$/, uglify))
  .pipe(gulpif(/\.css$/, cssSlam))
+ .pipe(gulpif(/\.html$/, cssSlam))
  .pipe(gulpif(/\.html$/, htmlminify))
  .pipe(project.rejoinHtml())

We'll probably make this change in the CLI as a temporary fix until someone is able to work on true style splitting/joining.

For those new to cssSlam, var cssSlam = require('css-slam').gulp();

is it going to be fixed in v0.6.0?

Documentation is misleading.

"project.splitHtml() returns a stream that extracts any inlined CSS & JS into individual files."

FWIW, I wanted this functionality to implement postcss-cssnext.

FWIW, I tried out @tony91 's fork and it seemed to work well for me and postcss (ie all the errors that postcss-cssnext produced were to do with my code, or non-standard polymer css). I needed to remove a '.pipe(project.analyzer)` from my gulp-tasks/project.js (which is part of the psk?), but after that it worked just fine.

Any solution?

This is still an issue for me, though @FredKSchott's addition does still work. Documentation and examples (including https://github.com/Polymer/polymer-build) state that it should separate HTML and CSS into individual files and run the appropriate transform on them.

Any developments? This issue is critical for Content Security Policy.

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.

Was this page helpful?
0 / 5 - 0 ratings