Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multipage requirejs #22

Open
MichaelKubovic opened this issue Sep 24, 2015 · 2 comments
Open

multipage requirejs #22

MichaelKubovic opened this issue Sep 24, 2015 · 2 comments

Comments

@MichaelKubovic
Copy link

Currently you bundle all javascript code together with almond into one huge file.
Imagine we could easily support more effective packaging by providing some more configuration options.

The approach I'm suggesting allows you to configure bundles (e.g. page specific), then leave r.js trace it's dependencies and leave the rest of code in the common bundle.

In the end you end up having:

  • require.js - module loader needed. no async loads in production however (intentionally)
  • common.js - vendor deps required across the page, requirejs config, default module which handles common parts of the site (think header or what)...
  • page.js - module containing page specific code + vendor deps traced by r.js

_requirejs.html

<script src="{{ asset('vendor/require.js', 'mad') }}"></script>
<script src="{{ asset('js/common.js', 'mad') }}"></script>
{% if app.environment == 'prod' and module %}
    <script src="{{ asset('js/' ~ module ~ '.js', 'mad') }}"></script>
{% endif %}
<script>
    requirejs.config({
        baseUrl: '{{ asset('js', 'mad') }}'
    });

    /**
     * The heart of our require.js setup!
     *
     *   1) Require the common.js file to get all the paths and shim setup
     *   2) Once that file is downloaded, download and execute app/default.js
     *      (a global module, executed on every page) and execute whatever
     *      page-specific app we have (e.g. app/homepage). This will do
     *      whatever craziness we want.
     */
    require(['common'], function (common) {
        {% if module and default is defined and default == false %}
            require(['{{ module }}']);
        {% elseif module %}
            require(['app/default', '{{ module }}']);
        {% else %}
            require(['app/default']);
        {% endif %}
    });
</script>

product.html.twig

{% block requirejs %}
    {{ include('MadnessT3Bundle::_requirejs.html.twig', {
        module: 'app/product'
    }) }}
{% endblock %}

kudos to @weaverryan for an impressive approach he has illustrated in his talk
http://www.slideshare.net/weaverryan/cool-like-frontend-developer-grunt-requirejs-bower-and-other-tools-29177248

I will be more than happy to prepare a PR if you find this appropriate for the generator.

@bezoerb
Copy link
Owner

bezoerb commented Nov 10, 2015

@MichaelKubovic this looks promising.

@bcosynot
Copy link

bcosynot commented Dec 6, 2015

Just to share a different implementation I am using the on my project.

So I have a base twig template with the following:

{% if app.environment == 'node' %}
            {% block javascriptsDev %}
            <script type="text/javascript" src="{{ asset('requirejs-config/config.js') }}"></script>
            <script type="text/javascript" data-main={% block javascriptDataMain %}"{{ asset('scripts/page.js') }}"{% endblock %}
                src="/bower_components/requirejs/require.js"></script>
            {% endblock %}
        {% else %}
            {% block javascriptsDist %} <script type="text/javascript" src="{{ asset('scripts/page.js') }}"></script>{% endblock %}
{% endif %} 

where page.js would be the page specific JS file.

Then the child template for the specific page would have:

{% block javascriptDataMain %}
"{{asset('scripts/page-customized.js') }}"
{% endblock %} 
{% block javascriptsDist %}
<script type="text/javascript"  src="{{ asset('scripts/page-customized.js') }}"></script>
{% endblock %}

Now, the page-customized.js:

require([ 'modules/common-scripts', 'jquery', 'other' ], function(common, jquery, other) {

    'use strict';
    common.init();
    var $ = jquery;

    /** Rest of the code goes here **/

});

In the above file modules/common-scripts is the JS common across the site for all pages.

This requires some changes to the requirejs grunt task as well. Basically, we need to process each of the customized files too. Here is the updated file

'use strict';
module.exports = function(grunt, options) {


    var files = grunt.file.expand(options.paths.app+'/scripts/*.js');
    var requirejsOptions = {};
    files.forEach(function(file) {
        var filename = file.split('/').pop();
        requirejsOptions[filename.split('.')[0]] = {
            options: {
                baseUrl: 'bower_components',
                name: 'almond/almond',
                include: 'appScripts/'+filename.split('.')[0],
                out: options.paths.dist+'/scripts/'+filename,
                mainConfigFile: options.paths.app+'/requirejs-config/config.js',
                preserveLicenseComments: false,
                useStrict: true,
                wrap: true,
                optimize: 'uglify2',
                generateSourceMaps: false,
            }
        };
    });
    return requirejsOptions;
};

All my page specific JS file are in app/Resources/public/scripts/ directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants