среда, 22 марта 2017 г.

RequireJS Plugin Builder for ECMAScript 6 Babel

Структура расположения папок и файлов:

/index.html

/build/build.js - итоговый собранный файл с помщью Node.js

/js/app/main/main.js
/js/app/simple/simple.js
/js/app/sum/sum.js
/js/app/class/class.js
/js/app/render/render.js

/js/config/require-config.js

/js/lib/requirejs/require.js
/js/lib/loader/loader.js

/js/lib/babel-standalone/babel.js

/js/lib/react/react.js
/js/lib/react/react-dom.js

/gulp.js
/gulpfile.js

/node_modules
/node.exe
/npm.cmd

Файл index.html

<!DOCTYPE html>
<html>
  <head>
    <script src="js/lib/requirejs/require.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script src="build/build.js"></script>
    <script>require(['main']);</script>
  </body>
</html>

Файл main.js

define(function (require) {
    var simple = require('simple');
    simple();
    var sum = require('loader!sum');
    require('loader!class');
    require('loader!render');
    alert(sum(1, 2));
});

Файл simple.js

define(function () {
    return function () {alert(1);}
});

Файл sum.js

define(function (require) {

    return (a, b) => a + b;

});

Файл class.js

define(function (require) {

    var sum = require('loader!sum');

    console.log(sum(1, 2));

    class A {
        constructor (a) {
            console.log('Hello ' + a);
        }
    }

    new A('world!');

});

Файл render.js

define(function (require) {
    var React = require('react');
    var ReactDOM = require('react_dom');
    ReactDOM.render(<span>Hello World 123</span>, document.getElementById('root'));
});

Файл require-config.js

requirejs.config({
      paths: {
          loader: 'js/lib/loader/loader'
        , babel: 'js/lib/babel-standalone/babel'
        , react: 'js/lib/react/react'
        , react_dom: 'js/lib/react/react-dom'

        , 'main': 'js/app/main/main'
        , 'class': 'js/app/class/class'
        , 'sum': 'js/app/sum/sum'
        , 'render': 'js/app/render/render'
        , 'simple': 'js/app/simple/simple'
      }
});

Файл loader.js

// ECMAScript 6 Babel Loader Plugin

// For Browser

// Define paths:

// requirejs.config({
//       config: {
//           loader: {
//               resolveModuleSource: function (source) {return 'loader!' + source;}
//           }
//       }
//     , paths: {
//           loader: 'js/lib/loader/loader'
//         , babel: 'js/lib/babel-standalone/babel'
//       }
// });

// Then use as a normal RequireJS plugin:

// require(['loader!path/to/my-es6-file'], function (MyEs6File) {
//     var myfile = new MyEs6File();
//     ...
// });

// or

// define(function () {
//     var myfile = new MyEs6File();
//     ...
// });

// For Server

// To use your existing client-side AMD modules in node, use global-define and set the path to the ECMAScript 6 Babel Loader Plugin.
// This so that when RequireJS tries to resolve the module name, it maps to the correct package.

// require('global-define')({
//       basePath: __dirname
//     , paths: {
//           loader: 'js/lib/loader/loader'
//       }
// });

define(['babel'], function(Babel) {

    var buildMap = {}
        , fetchFile
        , fs;

    function isBrowser () {return typeof window !== 'undefined' && window.navigator && window.document;}
    function isNode () {return typeof process !== 'undefined' && process.versions && !!process.versions.node;}
    function isRequireBuildProcess () {return isNode() && require.nodeRequire;}

    if (isBrowser()) {
        fetchFile = function (url, callback) {
            var xhr;
            if (window.XMLHttpRequest) {
                xhr = new XMLHttpRequest();
            } else if (window.ActiveXObject) {
                xhr = new window.ActiveXObject('Microsoft.XMLHTTP');
            }
            xhr.open('GET', url, true);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {callback(xhr.responseText);} // Do not explicitly handle errors, those should be visible via console output in the browser.
            };
            xhr.send(null);
        };
    } else if (isRequireBuildProcess()) {
        fs = require.nodeRequire('fs'); // nodeRequire is a method added by r.js
        fetchFile = function (path, callback) {
            callback(fs.readFileSync(path, 'utf8'));
        };
    } else if (isNode()) {
        fs = require('fs');
        fetchFile = function (path, callback) {
            callback(fs.readFileSync(path, 'utf8'));
        };
    }

    return {
          load: function (name, req, onload, config) {
            var url = req.toUrl(name + '.js');
            fetchFile(url, function (responseText) {
                var code = Babel.transform(responseText, {
                      presets: ['es2015', 'react']
                    , filename: 'embedded'
                    , sourceMaps: 'inline'
                }).code;
                if (config.isBuild) {buildMap[name] = code;}
                if (isNode() && !config.isBuild) {
                    var fileName = name + '.tmp';
                    fs.writeFileSync(fileName, code);
                    onload(req(fileName));
                    fs.unlink(fileName);
                } else {
                    onload.fromText(code);
                }
            });
          }
        , write: function (pluginName, moduleName, write) {
            if (moduleName in buildMap) {write.asModule(pluginName + '!' + moduleName, buildMap[moduleName]);}
          }
    };

});

Файл gulp.js

const task = process.argv.slice(2).join(' ')
        , command = `node ./node_modules/gulp/bin/gulp.js ${task}`
        , execProcess = require('child_process').exec(command);
execProcess.stdout.on('data', data => console.log(Buffer.isBuffer(data) ? data.toString() : data));
execProcess.stderr.on('data', data => console.log(Buffer.isBuffer(data) ? data.toString() : data));
execProcess.on('close', code => code === 0 ? console.log('Done') : console.log(`Exit code: ${code}`));

Файл gulpfile.js

const fs = require('fs')
        , del = require('del')
        , gulp = require('gulp')
        , requirejs = require('gulp-requirejs');

gulp.task('clean', () => del(['./build/**/*'], {force: true}));

gulp.task('requirejs', ['clean'], () => {
    eval('var requirejsConfig =' + fs.readFileSync('./js/config/require-config.js').toString().replace('requirejs.config(', '').replace(');', ';'));
    requirejsConfig.baseUrl = '.';
    const config = {};
    for (let key in requirejsConfig) {
        if (requirejsConfig.hasOwnProperty(key)) {config[key] = requirejsConfig[key];}
    }
    config.name = 'main';
    config.out = 'build.js';
    requirejs(config).pipe(gulp.dest('./build'));
});

Комментариев нет:

Отправить комментарий