Bottles and RequireJS

105 views
Skip to first unread message

Kevin Miller

unread,
Feb 5, 2013, 6:07:48 PM2/5/13
to fubumv...@googlegroups.com
Does anyone have experience using Bottles and RequireJS together?

We are starting to Bottle-ize some of our app's functionality. We use RequireJS for keeping our Javascript sane. 

Development Story:

From chatting with Ryan R. and he mentioned that for a development experience we can make Require's "baseURL' be something like _content/scripts as scripts in the Bottles content directory can get pulled  into there. We'll see how well this works soon.

Production: 

Ideally my bottles would be packaged to serve individual page experiences (mini-SPAs) each optimized (cat+min) at the Bottle level during the release process. 

Wondering what to do if we want to share AMD modules across bottles. 

KevM (BurgerKing)

Mike O'Brien

unread,
Feb 5, 2013, 6:10:52 PM2/5/13
to fubumv...@googlegroups.com
+1 Would be interested to hear about that too.

--
You received this message because you are subscribed to the Google Groups "FubuMVC Development Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fubumvc-deve...@googlegroups.com.
To post to this group, send email to fubumv...@googlegroups.com.
Visit this group at http://groups.google.com/group/fubumvc-devel?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Joshua Arnold

unread,
Feb 6, 2013, 11:52:09 AM2/6/13
to fubumv...@googlegroups.com
Bob might be the one to talk to about this.

Jeremy D. Miller

unread,
Feb 6, 2013, 12:03:33 PM2/6/13
to fubumv...@googlegroups.com
If you're still using fubu's asset pipeline, you have a full model in regards to a file on the file system and what the URL it is that serves it up.  If you need to change the url's to make require.js happy, you can do that in the asset pipeline regardless of where the file actually is.

One of the things that Bob and I have talked about is automatically "correcting" the Url for require.js delivered scripts in the asset pipeline so you can keep JS lib's closer to the views that use them without require.js going wonky.


Bob Pace

unread,
Feb 6, 2013, 2:49:47 PM2/6/13
to fubumv...@googlegroups.com
"From chatting with Ryan R. and he mentioned that for a development experience we can make Require's "baseURL' be something like _content/scripts as scripts in the Bottles content directory can get pulled  into there. We'll see how well this works soon."

This is exactly what we are currently doing in our main website.

A few other things we are doing in conjunction with this to make it all work (good or bad):

Since in production we use optimized version of our require files (through the requirejs optimizer) we have an extension method in use on our Html.spark master page

*this is an older require syntax there are more up to date ways of doing this now I believe*

    <script type="text/javascript">
        var require = {
            baseUrl: "/_content/scripts",
            !{this.ScriptCacheBust()},
            deps: ["${this.UseScriptName(ScriptMain)}"],
            waitSeconds: 300
        };
    </script>


        public static string UseScriptName(this IFubuPage page, string scriptMain)
        {
#if !DEBUG || RUN_COMPRESSED
            return scriptMain + "-built";
#endif
            return scriptMain;
        }

        public static string ScriptCacheBust(this IFubuPage page)
        {
            return "urlArgs: \"v={0}\"".ToFormat(GetVersionNumber());
        }

For us, the "version number" comes from an implementation that looks like this:

        private static string GetVersion()
        {
            DateTime maxLastModifiedDate = DateTime.MinValue;
            foreach (var package in PackageRegistry.Packages)
            {
                package.ForFolder(BottleFiles.WebContentFolder, directory =>
                {
                    directory = FileSystem.Combine(directory, "content");
                    var directoryInfo = new DirectoryInfo(directory);
                    var maxFromPackage = GetLatestModifiedDate(directoryInfo, DateTime.MinValue);
                    maxLastModifiedDate = MaxDate(maxLastModifiedDate, maxFromPackage);
                });
            }
            return maxLastModifiedDate.Ticks.ToString();
        }


We have one "main" require file (the one you would think of as data-main), but we include that as a dependency to other "main" files which exist in a one to one relationship to actual page routes (non partials).

At the top of our Html.spark:

<global ScriptMain="'main'" type="string" />

An example of another page using this master page overriding that main script:

Example.spark (for an ExampleViewModel, normal route that serves a view):
<set ScriptMain="'example-main'" />

contents of example-main.js

require(['main',
        'data-module',
        'dependencies',
        'get',
        'listed',
        'here'],
    function () {
    });

"main" in the above dependency list is the file you would normally think of as data-main for require.js, it contains all the boilerplate glue for the site.

The reason we include these intermediary files that list all the dependencies for a page stems from our use of "data-module" attributes which we use require.js to fetch (I believe Dovetail is doing this as well), but when you do something like that require no longer knows about those as dependencies which prevents the require optimizer tool from compressing/obfuscating them accurately.

This is another area where the asset pipeline could (and probably should) be doing this work instead, but we would need to register these 'data-module' dependencies with the asset pipeline somehow.

I spiked out some stuff (using IAssetPrecompiler) to parse it out of your require modules dependency list but that would only work if you manually listed them like we did above with our additional main files, maybe we can come up with something more clever in the future.

I would also like to see us make the use of 'data-module' an official part of something like a FubuMVC.RequireJs bottle sometime if that is feasible since I feel there is a lot of value in using that approach.

Kevin Miller

unread,
Feb 6, 2013, 6:21:06 PM2/6/13
to fubumv...@googlegroups.com
Bob, 

Thank you for the excellent details!

I am internalizing your post and compartmentalizing our application. We'll see how things fall out. I post back here when I have more information.

KevM 

Tom Riecken

unread,
Apr 15, 2014, 4:16:21 PM4/15/14
to fubumv...@googlegroups.com
Has anyone made any progress with this since last year? Or any git repos we can reference? We're working on an asteroid mining ThreeJS scene and could use some pointers!

Kevin Miller

unread,
Apr 17, 2014, 10:56:34 AM4/17/14
to fubumv...@googlegroups.com
Jeremy is doing some work with Mimosa.Js to wrangle bottles whose code is modularized with AMD. That is a work in progress and he can talk more about it. We chatted on Twitter about it recently. 


We are using RequireJS to package modules contained in our bottle. Our setup may not work for everyone. We have a Single Page App (SPA) per bottle. 

When packing bottles for release. We have automation which puts all the modules for the application into one place and optimizes each module into one JS file per bottle. That optimized JS file is then copied into the bottle’s content/scripts and packaged with the bottle contents. 

We have our RequireJS baseDir set to '_content/scripts’ and each bottle puts their modules in a unique path ‘/content/scripts/app/{bottle}/‘

I would like to have a way of putting all the bower sourced 3rd party (jQuery, etc.) modules into a common core module that all bottles share which is served from a common path but we haven’t done that yet.


KevM 
Reply all
Reply to author
Forward
0 new messages