Search code examples
javascriptgruntjsreactjsbrowserify

browserify for mixed-style project (grunt, reactjs + plain js)


What is the best way to configure browserify plugin in grunt for a project where reactjs is used along with the plain javascript? I.e. assuming that I want to use require(...) in every js file in my project and directory structure looks as follows:

/js/model/foo.js (plain javascript)
/js/model/... (plain javascript)
/js/services/foo-service.js (plain javascript)
/js/view/foo-item-view.jsx (reactjs)
/js/view/... (reactjs)
/js/main.js (plain javascript, entry point)
etc.

I want to apply reactjs transform for all the files within /js/view/... dir and then transform everything with browserify. I found no clean way to do that.

Is it possible at all?

UPDATE:

All right, I think my question was a little bit unclear. I understand that this is definitely doable and here is how I'm doing it right now (it looks like a hack to me):

// Project configuration.
grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  watch: {
    scripts: {
      files: ['web/js/**/*.js', 'web/html/index.html'],
      tasks: ['copy', 'react', 'browserify']
    }
  },
  copy: {
    main: {
      files: [
        {
          src: 'web/html/index.html',
          dest: 'target/web/index.html'
        },
        {
          cwd: 'web/js',                // source js dir
          src: ['**', '!**/*.jsx'],     // copy all files and subfolders to the temporary dor, except for jsx
          dest: 'target/web/tmp/js',    // destination folder, used by browserify
          expand: true                  // required when using cwd
        }
      ]
    }
  },
  react: {
    dynamic_mappings: {
      files: [
        {
          expand: true,
          cwd: 'web/js/view',
          src: ['**/*.jsx'],
          dest: 'target/web/tmp/js/view',
          ext: '.js'
        }
      ]
    }
  },
  browserify: {
    dist: {
      files: {
        'target/web/js/app.js': ['target/web/tmp/js/main.js'],
      }
    }
  }
});

This doesn't look elegant to me, because of extra copy instead of 'reactifying' sources in browserify task. May be I'm missing something and this solution can be simplified?


Solution

  • You can just run the jsx transform over everything. It won't do anything at all to regular JavaScript code.

    jsx compiler with bizare code

    Anything beyond that is an optimization, but just use watchify (or the watchify grunt plugin) and you won't notice.


    In response to the comment and edit... do you really need grunt here?

    npm i -D browserify watchify reactify
    

    And then in your package.json:

      "scripts": {
        "build": "browserify src/main.js -o dist/bundle.js",
        "watch": "watchify src/main.js -o dist/bundle.js"
      },
      "browserify": {
        "transform": ["reactify"]
      }
    

    You can also just have everything be .js, it's much simpler imo. If you need to some other things like css preprocessors, image compression, sprite sheets, running tests, etc. you should use a tool like grunt/gulp for that.

    For browserify, I find it's much easier to just use watchify on its own.