magnars / optimus

A Ring middleware for frontend performance optimization.
364 stars 23 forks source link

How to specifiy optimizations on a per-bundle basis. #30

Closed BorisKourt closed 9 years ago

BorisKourt commented 9 years ago

In the main example you provide three asset bundles in get-assets which are then piped through a single optimization function. What is the correct way to direct specific bundles to different optimization functions? (i.e. post images to one, while theme images to another. In order to use different transform-images settings)

magnars commented 9 years ago

In your specific case, I use the transform-images :regexp option to target specific images.

However, what you want can also be done on a more general basis. The optimization function is just that - function that is passed all assets, and then does whatever optimizations it seems fitting. You can filter the assets lists based on each asset's :bundle property there.

You can also optimize a subset of assets as part of your get-assets function. The optimization functions both take assets and return assets, so they are quite flexible in this way.

Makes sense? Please do let me know what solution you chose, and how it worked out for you.

borkdude commented 9 years ago

I have a similar question.

My get-assets function looks like this:

(defn get-assets []
  (concat
    (assets/load-bundle "public"
                                    "lib.js"
                                    ["/jquery/1.11.1/jquery.js"
                                     ...])
    ...
    (assets/load-bundle "public"
                       "app.js"
                       [(if (env :dev)
                          "/js-dev/lob-dev.js"
                          "/js-prod/lob.min.js")])))

To export these assets, I use this code:

(def options nil)

(defn add-cdn-base-url-to-assets [assets]
  (map #(assoc % :base-url "//assets") assets))

(defn my-optimize [assets options]
  (-> assets
      (optimizations/all options)
      (add-cdn-base-url-to-assets)))

(defn export-assets []
  (-> (get-assets)
      (my-optimize options)
      (optimus.export/save-assets "./cdn-export/")))

When (env :dev) is false the assets contain an already optimized .js file, compiled by ClojureScript of approx. 500 kb. Exporting takes 147 seconds on my machine. When I uncomment the bundle app.js, exporting takes 3 seconds. How I can skip optimizations for this bundle?

magnars commented 9 years ago

Here are some ideas:

Both get-assets and the optimization functions all take a list of assets and return a list of assets, so you should be able to work around this.

Any thoughts?

borkdude commented 9 years ago

@magnars

Could you give a small example how this is done with Optimus of idea 1 and idea 2? I think it would help to include that in the README.

Meanwhile I fixed it by bypassing the minify-js-assets:

(defn my-optimize [assets options]
  (-> assets
      #_(optimizations/minify-js-assets options)
      (optimizations/minify-css-assets options)
      (optimizations/inline-css-imports)
      (optimizations/concatenate-bundles)
      (optimizations/add-cache-busted-expires-headers)
      (optimizations/add-last-modified-headers)))
magnars commented 9 years ago

@borkdude

This would be one way of doing it:

(defn should-be-minified? [asset]
  ...)

(defn my-optimize [assets options]
  (-> (concat (-> assets
                  (filter should-be-minified?)
                  (optimizations/minify-js-assets options))
              (-> assets
                  (remove should-be-minified?)))
      (optimizations/minify-css-assets options)
      (optimizations/inline-css-imports)
      (optimizations/concatenate-bundles)
      (optimizations/add-cache-busted-expires-headers)
      (optimizations/add-last-modified-headers)))
borkdude commented 9 years ago

@magnars That seems simple enough, thanks!

borkdude commented 9 years ago

For anyone referencing this later, here's what I ended up with eventually:

(defn should-be-minified? [asset]
  (not= "/js-prod/lob.min.js" (:path asset)))

(defn minify-js [assets options]
  (concat (-> (filter should-be-minified? assets)
              (optimizations/minify-js-assets options))
          (remove should-be-minified? assets)))

(defn log-asset-action [assets message]
  (log/info message)
  assets)

(defn my-optimize [assets options]
  (->
   assets
   (log-asset-action "Minifying JS")
   (minify-js options)
   (log-asset-action "Minifying CSS")
   (optimizations/minify-css-assets options)
   (log-asset-action "Inlining CSS imports")
   (optimizations/inline-css-imports)
   (log-asset-action "Concatenating bundles")
   (optimizations/concatenate-bundles)
   (log-asset-action "Adding cache busting expires headers")
   (optimizations/add-cache-busted-expires-headers)
   (log-asset-action "Adding last modified headers")
   (optimizations/add-last-modified-headers)))
magnars commented 9 years ago

Nice, thanks for the follow up! :+1: