canjs / can-compile

Compile CanJS Mustache and EJS views for lightning fast production apps
http://daffl.github.com/can-compile
MIT License
35 stars 15 forks source link

Compiled .ejs doesn't render with RequireJS + Almond app #14

Closed ghost closed 10 years ago

ghost commented 10 years ago

Hey Daffl,

I'm building an app with RequireJS, compiled through Almond for production. Using latest CanJS (2.0.3) with EJS views.

I can get can-compile to work with RequireJS's build through Grunt, and I can see the compiled view in the build at the end of the file. But when running my builded app the view is not rendered.

Here's my require-config which grunt runs through grunt-contrib-requirejs:

// requirejs global config
require.config({
    baseUrl: '/static/js/gamificationamd/src',
    paths: {
        almond: "../../vendor/almond/almond",
        jquery: '../../vendor/jquery/jquery',
        xdomainrequest: '../../vendor/xdomainrequest/xdomainrequest-amd',
        can: '../../vendor/can/can',
        jquerycookie: '../../vendor/jquerycookie/jquerycookie',
        tooltipster: '../../vendor/tooltipster/js/jquery.tooltipster.amd',
        config: 'config/config',
        bar: 'bar/bar',
        views: 'views/build'
    },
    map: {
        // http://requirejs.org/docs/jquery.html#noconflictmap
        '*': {
            'jquery': 'jquery-private'
        },
        'jquery-private': { 'jquery': 'jquery' },
    }
});

And my concerned Grunt tasks:

// Can-compile to include EJS views in RequireJS Build
    cancompile: {
      bar: {
        src: ['static/js/gamificationamd/src/**/*.ejs'],
        out: 'static/js/gamificationamd/src/views/build/views.js',
        wrapper: 'define(["can/view/ejs"], function(can) { {{{content}}} });'
      }
    },

    // RequireJS for build version of bar
    requirejs: {
      bar: {
        options: {
          baseUrl: 'static/js/gamificationamd/src',
          mainConfigFile: 'static/js/gamificationamd/src/require-config.js',
          deps: ['gamificationamd'],
          insertRequire: ['gamificationamd'],
          name: '../../vendor/almond/almond',
          out: 'static/js/gamificationamd/bar.js',
          optimize: 'uglify2',
          generateSourceMaps: false,
          preserveLicenseComments: false,
          findNestedDependencies: true,
          wrap: true
        },
      },
    }

Thanks

ghost commented 10 years ago

Oh, actually concerning the note in the Readme:

"Always make sure that the output file is in the same folder as the root level for the views that are being loaded. So if your CanJS applications HTML file is in the app folder within the current directory use a filename within that folder as the output file:"

Our app is a third-party script loaded on multiple sites, from multiple locations. Can this be the source of the problem?

daffl commented 10 years ago

You can add a custom normalizer (function(filename) { return 'actual filename'; }) but basically what you have to make sure is that the filename is the same as the one you are referencing via CanJS. The problem is if you, say, build views from js/ and into dist/ and you are referencing my/view.ejs without a custom normalizer the view id will become dist_my_view_ejs where it actually should be my_view_ejs.

ghost commented 10 years ago

Where do I add the custom normalizer?

Thanks

ghost commented 10 years ago

Nevermind the last comment, checked the docs.

daffl commented 10 years ago

Pull request #10 did fix a bug with using the normalizer. Haven't done a release yet though, so I can't guarantee it will work.

ghost commented 10 years ago

It does not on my end, unfortunately. My custom normalizer isn't used in compile.js.

Does the pull request also affects the Grunt task?

daffl commented 10 years ago

Ok, I released 0.4.1 which should fix that issue (by including #10).

ghost commented 10 years ago

Exactly what I was hacking on, but you beat me to it.

It's working for the normalizer, but I still can't get the preloading to work. Problem is, the module where I render the view with can.view(...) is absolute and not relative.

Will an absolute URL like /static/js/views/bar.ejs work too when normalized?

Again I need this since the script will be injected on various "root pages". So is it actually possible to make it work?

daffl commented 10 years ago

As long as the normalizer returns the same filename you should be fine.

ghost commented 10 years ago

Alright I'll take a look when I have a moment. Thanks for the help.

ghost commented 10 years ago

Is there an easy way I can test the normalizer?

daffl commented 10 years ago

I would console.log the filename passed to the normalizer and what you are about to return.

ghost commented 10 years ago

Alright will do, thanks again for the support fellow Canadian :+1:

ghost commented 10 years ago

Works like a charm now. Here's what I added in lib/compile.js around line 47, only for testing purpose, removed after of course:

console.log(can.view.toId(normalizer(filename)));
console.log(can.view.toId(normalizer('/path/iwanted/to/test')));

And ran the grunt task