1

我正在尝试配置 Grunt & Browserify 以输出一个独立的包,其中包含 React 作为 CommonJS 模块,以便其他包可以引用它。

我现在遇到的问题是别名似乎不起作用。尽管在vendor下面的外部包中指定了别名,并且指定了这些模块应该在所有其他模型中从外部加载,但我在运行时仍然收到错误,指出找不到“react”模块。

如果有人知道我的grunt-browserify语法可能有什么问题,那就太好了:

var externals = [
  'react',
  'react/addons',
  'jquery',
  'backbone',
  'react-router'
];

module.exports = function(grunt) {

  grunt.config.set('browserify', {
    main: {
      src: 'assets/js/main.jsx',
      dest: '.tmp/public/js/main.js',
      options: {
        debug: true,
        extensions: ['.jsx'],
        external: externals,
        transform: [
          ['babelify', {'stage': 0}]
        ]
      }
    },
    signup: {
      src: 'assets/js/signup.jsx',
      dest: '.tmp/public/js/signup.js',
      options: {
        debug: true,
        extensions: ['.jsx'],
        external: externals,
        transform: [
          ['babelify', {'stage': 0}]
        ]
      }
    },
    login: {
      src: 'assets/js/login.jsx',
      dest: '.tmp/public/js/login.js',
      options: {
        debug: true,
        insertGlobals: true,
        extensions: ['.jsx'],
        external: externals,
        transform: [
          ['babelify', {'stage': 0}]
        ]
      }
    },
    vendor: {
      src: [
        './node_modules/react/dist/react.js',
        './node_modules/react/dist/react-with-addons.js',
        './node_modules/jquery/dist/jquery.js',
        './node_modules/backbone/backbone.js',
      ],
      dest: '.tmp/public/js/dependencies/vendor.js',
      options: {
        debug: false,
        alias: {
          'react:': './node_modules/react/dist/react.js',
          'react/addons': './node_modules/react/dist/react-with-addons.js',
          'jquery': './node_modules/jquery/dist/jquery.js',
          'backbone': './node_modules/backbone/backbone.js',
          'react-router': './node_modules/react-router/lib/index.js'
        },
        shim: {
          react_router: {
            path: './node_modules/react-router/lib/index.js',
            exports: 'react-router'
          }
        },
        external: null
      }
    }
  });

  grunt.loadNpmTasks('grunt-browserify');
};
4

3 回答 3

0

我发现这个链接对我很有帮助。按照这种方法,您的vendor部分应该看起来像

vendor: { src: ['.'], dest: '.tmp/public/js/dependencies/vendor.js', options: { debug: false, alias: externals.map(function(module) { return module + ':'; }), shim: { react_router: { path: './node_modules/react-router/lib/index.js', exports: 'react-router' } }, external: null } }

我不确定shim上面的部分,因为我只为react模块尝试过这个。

于 2015-06-17T11:49:50.617 回答
0

这是 React 的完整 Grunt 配置:

我创建了一个虚拟项目,因此您可以构建它进行测试。

项目的 Gruntfile.js:

module.exports = function (grunt) {

let concat = {};
let clean = {};
let uglify = {};
let copy = {};
let htmlmin = {};
let cssmin = {};
let browserify = {};
let watch = {};
let template = {};
let run = {};

/* React configuration. */

const reactSourcePath = './source';
const reactCompiledPath = './client';
const reactHtmlPathDest = './client/index.html'
const reactTargetName = "react";
const reactFileName = "react_main";

/* ### TASK CONFIGURATIONS ### */ 

/* Clean compiled files. */
clean[reactTargetName] = [
    `${reactCompiledPath}`
];

/* Concatenate all CSS files to one. */
const cssConcatSourceTemplate = `${reactSourcePath}/**/**.css`;
const cssDestinationFile = `${reactCompiledPath}/css/${reactFileName}.css`;

concat[reactTargetName] = {
    src: [cssConcatSourceTemplate],
    dest: cssDestinationFile
};

/* Convert JSX to JS, prepare JS files for a browser and copy to the destination. */
const jsSourceFile = `${reactSourcePath}/index.js`;
const jsDestinationFile = `${reactCompiledPath}/js/${reactFileName}.js`;

browserify[reactTargetName] = { 
    options: {
        transform: [['babelify', {presets: ['es2015', 'react']}]]
    },
    files: {
        [jsDestinationFile]: jsSourceFile
    }
};

/* Replace js/css placeholders and copy html file to destination. */
const applicationData = {
    css: [
        './css/react_main.css'
    ],
    js: [
        './js/react_main.js'
    ]
};

var jsFiles = "";
var cssFiles = "";

applicationData.css.forEach(function(item) {
    cssFiles = cssFiles + `\n<link rel="stylesheet" type="text/css" href=${item}>`;
});

applicationData.js.forEach(function(item) {
    jsFiles = jsFiles + `\n<script type="text/javascript" src=${item}></script>`;
});

template[reactTargetName] = {
    options: {
        data: {
            appName: '<%= pkg.name %>' + '-react',
            productVersion: '<%= pkg.version %>',
            reactEmbeddedCssFiles: cssFiles,
            reactEmbeddedJsFiles: jsFiles
        }
    },
    files: {
        [`${reactHtmlPathDest}`]: `${reactSourcePath}/index.template.html`,
    }
};

/* Uglify react JS file. */
uglify[reactTargetName] = { 
    files: {
    [jsDestinationFile]: jsDestinationFile
}
};

/* Copy bootstrap CSS/JS files. */
copy[reactTargetName] = {
    files: {
        [`${reactCompiledPath}/css/bootstrap.min.css`]: 'node_modules/bootstrap/dist/css/bootstrap.min.css',
        [`${reactCompiledPath}/js/bootstrap.min.js`]: 'node_modules/bootstrap/dist/js/bootstrap.min.js',
        [`${reactCompiledPath}/js/jquery.min.js`]: 'node_modules/jquery/dist/jquery.min.js',
    }
}

/* Minify HTML files. */
htmlmin[reactTargetName] = {
    options: {
        removeComments: true,
        collapseWhitespace: true
    },
    files: {
        [`${reactHtmlPathDest}`]: `${reactHtmlPathDest}`
    }
};

/* Minify react CSS file. */
cssmin[reactTargetName] = {
    files: {
        [cssDestinationFile]: cssDestinationFile 
    }
};

/* Watch for any changes in react app. 
There are three separate watches for css, js, and html files. */
watch[reactTargetName + '_css'] = {
    files: [`${reactSourcePath}/**/*.css`],
    tasks: [`concat:${reactTargetName}`],
    options: {
        livereload: true
    }
};

watch[reactTargetName + '_js'] = {
    files: [`${reactSourcePath}/**/*.js`],
    tasks: [`browserify:${reactTargetName}`],
    options: {
        livereload: true
    }
};

watch[reactTargetName + '_hmtl'] = {
    files: [`${reactSourcePath}/**/*.html`],
    tasks: [`template:${reactTargetName}`],
    options: {
        livereload: true
    }
};

/* Jest tests */
jestTestsTaskName = reactTargetName + '_jest_tests';
run[jestTestsTaskName] = {
    exec: 'npm test'
  };

/* Generate task names for react. */

var reactTasks = {
    debug: [
        "clean", 
        "browserify", 
        "concat", 
        "copy", 
        "template"
    ].map(x => x + `:${reactTargetName}`),
    release: [
        "clean", 
        "browserify", 
        "concat", 
        "copy", 
        "template", 
        "htmlmin", 
        "uglify", 
        "cssmin"
    ].map(x => x + `:${reactTargetName}`)
};

grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    watch:watch,
    copy:copy,
    concat:concat,
    clean:clean,
    uglify:uglify,
    template:template,
    browserify: browserify,
    htmlmin: htmlmin,
    cssmin: cssmin,
    run:run
});

grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-template');
grunt.loadNpmTasks("grunt-browserify");
grunt.loadNpmTasks("grunt-contrib-htmlmin");
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-run');

grunt.registerTask('react_build_debug', reactTasks.debug);
grunt.registerTask('react_build_release', reactTasks.release);

}

于 2018-08-06T22:21:23.467 回答
0

我正在使用 ReactJS 开发 Sails 0.11.0 项目。我开始我的 grunt watchify 任务来处理重新捆绑/转换我的应用程序代码,同时使用供应商任务来捆绑模块化代码。我还必须将 vendor.js 添加到我的布局文件中。

我对 grunt 世界还很陌生,所以可能有更有效的方法来做到这一点。

浏览器化.js

var externals = [
  'react',
  'react/addons',
  'jquery',
  'react-router',
  'events'
 ]

module.exports = function(grunt){
  grunt.config.set('browserify', {
    dist: {
      options: {
        external: externals,
        transform: [
          ['babelify', {
            loose: 'all'
          }]
        ]
      },
      files: {
        ".tmp/public/js/bundle.js": ["assets/js/bundle.js", "react/**/*"]
      }
    },
    vendor: {
      src: [
        './node_modules/react/dist/react.js',
        './node_modules/react/dist/react-with-addons.js',
        './node_modules/jquery/dist/jquery.js',
        './node_modules/react-router/lib/index.js',
        './node_modules/events/events.js'
      ],
      dest: '.tmp/public/js/dependencies/vendor.js',
      options: {
        alias: {
          'react': './node_modules/react/dist/react.js',
          'react/addons': './node_modules/react/dist/react-with-addons.js',
          'jquery': './node_modules/jquery/dist/jquery.js',
          'react-router': './node_modules/react-router/lib/index.js',
          'events': './node_modules/events/events.js'
        }
      }
    }
  });

  grunt.loadNpmTasks('grunt-browserify');
}

任务/配置:

module.exports = function(grunt) {

    grunt.config.set('watch', {
        api: {

            // API files to watch:
            files: ['api/**/*', '!**/node_modules/**']
        },
        assets: {

            // Assets to watch:
            files: ['assets/**/*', 'tasks/pipeline.js', '!**/node_modules/**'],

            // When assets are changed:
            tasks: ['syncAssets' , 'linkAssets', 'browserify:dist']
        },
    react: {
      files: ['react/**/*'],
      tasks: ['browserify:dist']
    }
    });

    grunt.loadNpmTasks('grunt-contrib-watch');
};
于 2015-08-07T16:56:45.010 回答