seiffert / require-jsx

A require.js plugin that allows you to use JSX files as require.js dependencies.
96 stars 17 forks source link

Question about compilation. #1

Open jordwalke opened 11 years ago

jordwalke commented 11 years ago

This project is very cool. I'll certainly end up using this. Will require.js ensure that the compilation happens on the server as part of the build step? If not, is there some way that we can message to users that compilation in the browser should not be done in production (due to the huge bloat of file size caused by including the compiler and the CPU required to compile)?

seiffert commented 11 years ago

Hi @jordow and thanks for the feedback! Sadly, I wasn't able to get the compilation with r.js to work so far. I've spent a couple of hours in the #reactjs chat with @petehunt and @zpao on this topic, but we weren't able to find a good solution in the end. The problem seems to be that the built version of JXSTransformer includes require calls that aren't compatible with require.js - which normally shouldn't be a problem. In this case however, it leads to a mismatched anonymous define() error in the browser (after a successful compilation on the server).

This require.js plugin should definitely notify the user not to use in-browser-JXS-transformation in production. Do you have a better idea than just writing this message to the browsers JS console?

jordwalke commented 11 years ago

Browser console is a good start.

camspiers commented 11 years ago

I've been able to get the compiled jsx in a built version with r,js using PR https://github.com/seiffert/require-jsx/pull/5 and a build config that has the following: (note this isn't the full config, just the relevant parts)

({
    exclude: ['JSXTransformer', 'jsx'],
    include: ['jsx!app'],
    onBuildWrite: function (moduleName, path, singleContents) {
        return singleContents.replace(/jsx!/g, '');
    }
})

What is does is write the compiled version to the file with 'jsx!' removed whenever found. So something like:

define('Component1', ['jsx!Component2'], function (Component2) {});

becomes:

define('Component1', ['Component2'], function (Component2) {});

This isn't the best solution due to the potential to replace instances of 'jsx!' where it isn't desirable, but it is at least working.

ssorallen commented 10 years ago

@camspiers Can you elaborate on your build setup? Despite excluding JSXTransformer and jsx, I am getting errors since jsx depends on JSXTransformer. I am using your patch from #5:

Tracing dependencies for: main
Error: Parse error using esprima for file: /.../build/js/libs/JSXTransformer.js
Error: Line 11478: Unexpected token if
In module tree:
    main
      jsx

Error: Error: Parse error using esprima for file: /.../build/js/libs/JSXTransformer.js
Error: Line 11478: Unexpected token if
In module tree:
    main
      jsx

    at /usr/local/share/npm/lib/node_modules/requirejs/bin/r.js:23648:47
camspiers commented 10 years ago

My amd.config.js looks like this:

require.config({
    baseUrl: 'source/js',
    paths: {
        JSXTransformer: '../bower_components/react/JSXTransformer',
        jsx: '../bower_components/require-jsx/jsx',
        react: '../bower_components/react/react',
        almond: '../bower_components/almond/almond'
    }
});

My amd.build.js looks like this:

({
    baseUrl: '.',
    mainConfigFile: 'amd.config.js',
    name: 'almond',
    out: '../../prod/app.js',
    exclude: ['JSXTransformer', 'jsx'],
    include: ['jsx!app'],
    onBuildWrite: function (moduleName, path, singleContents) {
        return singleContents.replace(/jsx!/g, '');
    },
    preserveLicenseComments: false
})

bower.json like this:

{
    "name": "app",
    "version": "0.0.0",
    "dependencies": {
        "rjs": "2.1.8",
        "react": "0.4.1",
        "almond": "0.2.6",
        "require-jsx": "git://github.com/camspiers/require-jsx.git#patch-1"
    }
}

And the command I am running is:

node bower_components/rjs/dist/r.js -o js/amd.build.js

Excuse the old versions, the project was a while ago.

Hope this helps!

felipecrv commented 10 years ago

@ssorallen this error is caused by some preprocessing that removes 'use strict' from JSXTransformer.js.

In the original file, ... === 'use strict'becomes ... ===. Such a mess!

felipecrv commented 10 years ago

I figured out how to make it work.

Used @camspiers config:

({
    exclude: ['JSXTransformer', 'jsx'],
    include: ['jsx!app'],
    onBuildWrite: function (moduleName, path, singleContents) {
        return singleContents.replace(/jsx!/g, '');
    }
})

And replaced occurrences of 'use strict' by 'use ' + 'strict' when it's used as a value in JSXTransformer.js.

ssorallen commented 10 years ago

And replaced occurrences of 'use strict' by 'use ' + 'strict' when it's used as a value in JSXTransformer.js.

@philix, that sounds like the bit I was missing. Thanks for pointing that out. I will give that a shot and see if that fixes my build.

maglar0 commented 10 years ago

I still couldn't get it working the way described above, but used the ideas to solve it in (what I think is) a different way. I remove "jsx!" and do the JSX->JS transformation myself before handing the files over to r.js and almond. I have my files in ./app, ./app/jsx (this is where the JSX files live) and ./lib. My requirejs config is like this:

requirejs.config({
    baseUrl: "/js2/lib",
    paths: {
        app: "/js2/app",
        appjsx: "/js2/app/jsx",
        jsx: "jsx",
        JSXTransformer: "JSXTransformer"
    },
    shim: {
        exports: "JSXTransformer"
    }
});

and my build.js file is like this:

({
    baseUrl: "../build",
    out: "main-built.js",
    name: "lib/almond",
    include: ["app/a"],
    exclude: [],
    preserveLicenseComments: false,
    generateSourceMaps: true,
    optimize: "uglify2",
    insertRequire: ["app/a"],
    onBuildWrite: function(moduleName, path, singleContents) {
        return singleContents
            .replace(/console\.(log|assert)\([^))]*\);/g, "");
    },
    paths: {
        appjsx: "jsx"
    }
})

and my Makefile can be found at https://gist.github.com/maglar0/9762505 .

felipecrv commented 10 years ago

@maglar0 what are the error messages? r.js fails for all sorts of reasons. If you're getting undefined is not a function message you should probably disable sourceMap in JSXTransformer as I did here.

facebook/react#972 may help too.

maglar0 commented 10 years ago

@philix It works when I set sourceMap to false as you did in that link, together with the earlier change of === 'use strict' to === 'use '+'strict'. Thanks for the effort you have put into solving this, I got totally nonsensical error messages like "undefined is not a function" without any reference to line numbers so didn't know where to start at all.

However, I strongly prefer not to fork JSXTransformer.js and the source map of the output when doing it this way references nonsense files like "../app/jsx/d!jsx", thus I will continue to do the JSX transform myself and then hand over the files to r.js.

felipecrv commented 10 years ago

@maglar0 your approach avoids a lot of headaches :+1: