cujojs / curl

curl.js is small, fast, extensible module loader that handles AMD, CommonJS Modules/1.1, CSS, HTML/text, and legacy scripts.
https://github.com/cujojs/curl/wiki
Other
1.89k stars 216 forks source link

using style! for putting all css in one .js bundle using grunt #221

Open manast opened 10 years ago

manast commented 10 years ago

Hello,

I have been experimenting with grunt and the undocumented style plugin in order to create a single .js file that contains all the css, where every css file is wrapped into a define function and returned as a string.

I made it work but some things are worth mention:

1) I created a css.js file using grunt-contrib-concat with this task

concat: {
      dist: {
        options: {
          process: function(src, filepath){
            return "define('text!"+filepath+"', [], function(){return '"+src.replace(/\'/g, "\\'")+"'});"
          }
        },
        src: 'build/css/**/*.*',
        dest:'build/css.js'
      }
    }

Note that I use in the module name the text! plugin. This will create a single css.js file with all the css files as AMDs.

2) I had to modify the style plugin so that it uses the text! plugin to read the modules:

138:    req(['text!'+absId], function (cssText) {

Not sure what I had to to this. If I didn't do it, curl would try to append a .js extension to every module to fetch and nothing works. This is the reason I also had to use the text! plugin when defining my css modules...

3) The following string replacement is extremely slow:

69: // for safari which chokes on @charset "UTF-8";
70: // TODO: see if Safari 5.x and up still complain
71: allCssText = allCssText.replace(/.+charset[^;]+;/g, '');    

In the order of 3-4 seconds for a 100Kb minimized CSS. I had to out comment it in order to make this solution feasible at all. On safari 6.0.5 everything seems to work quite well, not sure about other safari versions though... But I am using .less as css preprocesor, so in my case I may be safe. Honestly I do not really understand whats the purpose of that string replacement.

manast commented 10 years ago

4) For debugging, the style plugin is not very convenient, so you want to use the css (or link) plugin so that you can easily see the source file for every css rule. This can be accomplished by aliasing the style plugin path in development mode. For example:

<script> curl.paths.style = '/js/curl/plugin/css' </script
unscriptable commented 10 years ago

Hey @manast,

So many things to respond to! :)

1) Manual bundling via grunt-contrib-concat:

The curl/plugin/css and curl/plugin/style plugins coordinate through the curl/cram/css plugin. I hadn't considered the use cases for the style plugin outside of cram. The curl/cram/css plugin outputs something like this:

define('theme/base.css', ['curl/plugin/style', 'require'], function (injector, require) { var text = "/*css text goes here */"; if (0) text = injector.translateUrls(text, require.toUrl("")); return text; });

You could probably just do something like this, instead:

define('theme/base.css', function () { return "/*css text goes here */"; });

2) Appending ".js" to css modules

I have no idea why it would do this. curl will normally add ".js" to urls, but not to ids. Ah ha, it may have been adding the ".js" if it wasn't finding the module in the bundle. Maybe there was an id mismatch?

3) Good to know! I will create a github issue to fix this. Also: maybe it isn't even needed any more. I can't remember the exact versions atm, but early Safari would crash hard if the charset rules weren't at the very top of the file.

4) Yah, if you're using cram.js, you can use the css! plugin at dev time and it converts to using the style! plugin in production/bundles.