modular icon indicating copy to clipboard operation
modular copied to clipboard

Add web resource module that implement get-javascript-paths or get-css-paths

Open ordnungswidrig opened this issue 10 years ago • 4 comments

I like to be able include a webjar resource like "jquery" and have that component provide a get-javascript-paths function like the ClojureScriptBuilder does. The same would be feasible for css webjars, too.

ordnungswidrig avatar Mar 27 '15 10:03 ordnungswidrig

That's a great idea. I have a modular.bidi component that brings in web resources from the classpath that I use for bootstrap, react, jquery, etc. but I have to manually add the js paths of course - that's not very cohesive.

malcolmsparks avatar Mar 27 '15 15:03 malcolmsparks

The same would be great to the LessCompiler. Maybe something like anAssetProviderorResourceProvider` Interface would do it? I'm not sure on the interface if -- like in the case of bootstrap -- a single component might provide different resource types like css and javascript.

Either have a single interface

(AssetProvider
   ;; returns a map of types to uris / uri-paths
  (assets [this]))

;; or
(AssetProvider
   ;; returns list of assets for that type (:js, :css...)
  (assets [this type]))

or have multiple interface for Javascript and Css.

I'm leaning to the former because I cannot see why different asset types would need different interfaces.

The inferfaces above all return a list/map of strings. I don't know if that should be extended to support e.g. different script languages (matching the "type" attribute of the <script> tag). A simple solution for that case is to map different script types to different "asset types", i.e. javascript -> :js, dart -> :dart.

ordnungswidrig avatar Mar 30 '15 08:03 ordnungswidrig

Yes good point. I hadn't thought about LessCompiler but you're right, it makes perfect sense.

I've never been 100% happy with the JavascriptPaths protocol, it was named that way in a hurry and was when I was playing with the idea that components could/should have multiple protocols. I think the benefits outweigh the trade-offs, because of the cohesion that results. As a name, AssetProvider feels better, and the name matches bidi's new RouteProvider protocol.

Would we end up having a component per webjar? (see webjars.org). That seems painful. I wonder if there's a better way of doing it. I have quite a few JS files I use regularly now (bootstrap, jquery, momentjs, reactjs...)

It would be nice to have a consistent way of indicating a preference for minified or original versions of JS and CSS too.

Anyway, this is a perfect example of the benefit of good component cohesion

  • all these nasty details should be buried into a single component rather than the implicit coupling that results in having to manually hack HTML templates...

I don't think the asset type is that valuable, so I don't think different asset types should have different interfaces and agree with your preference here.

How does the component compose the routes - via bidi's path-for ? That would make the component depend on bidi but I don't see another way.

On 30 March 2015 at 09:04, Philipp Meier [email protected] wrote:

The same would be great to the LessCompiler. Maybe something like an AssetProviderorResourceProvider` Interface would do it? I'm not sure on the interface if -- like in the case of bootstrap -- a single component might provide different resource types like css and javascript.

Either have a single interface

(AssetProvider ;; returns a map of types to uris / uri-paths (assets [this])) ;; or (AssetProvider ;; returns list of assets for that type (:js, :css...) (assets [this type]))

or have multiple interface for Javascript and Css.

I'm leaning to the former because I cannot see why different asset types would need different interfaces.

The inferfaces above all return a list/map of strings. I don't know if that should be extended to support e.g. different script languages (matching the "type" attribute of the

— Reply to this email directly or view it on GitHub https://github.com/juxt/modular/issues/26#issuecomment-87584202.

malcolmsparks avatar Mar 30 '15 21:03 malcolmsparks

I guess having a single component cover multiple webjars is a very good idea. A WebResources component could take a map of resource paths and build a route with a common uri-context prefix:

(make new-web-resources config
  :uri-context "/assets"
  :resources
  {:react "META-INF/resources/webjars/react/0.11.1" ;; from .jar
   :jquery "META-INF/resources/webjars/jquery/2.1.3" ;; from .jar
   :whatever "/js/whatever"}) ;; from resource directory resources/js/whatever

I wonder, however, how to enumerate these actual resources like the CljsBuilder does. The current WebResource doesn't do that and for the case of js webjars which might contain minified and regular versions you cannot simply scan the jar. That means you need to explicitly list the required files and the component is not more than some kind of wrapper around a bidi route.

Nevertheless I find the following more convenient than listing the css and js names in the html files "by hand":

(system-map
{:jquery
 (make-web-resource :resource-prefix "META-INF/resources/webjars/jquery/2.1.3" 
                    :files ["jquery.min.js"])
 :bootstrap
 (make-web-resource :resource-prefix "META-INF/resources/webjars/bootstrap/3.3.2-1" 
                    :files ["css/bootstrap.css" #"js/.*\\.js"])})

Another point that is annoying is that the version of the webjar as declared in project.clj must match the resource-prefix. Maybe we can use https://github.com/webjars/webjars-locator-core like https://github.com/weavejester/ring-webjars does.

ordnungswidrig avatar Mar 31 '15 13:03 ordnungswidrig