在webpack react应用程序

时间:2015-07-25 23:19:20

标签: reactjs webpack

tldr :我能够require一切能够让应用程序运行,但是如果我在测试中require模块(在应用程序中) - 请参阅dir结构下面的文件,整个依赖链断裂。

我遇到了一些问题require - 来自我的app/test目录(在我的webpack React.js应用程序中)的组件,我没有任何困难require来自任何其他文件在/app文件夹中。这是目录结构

app
  /components/checkout.jsx
  /components/button.jsx
  /test/test.js 
  index.jsx  
dist
node_modules
webpack.config.js
package.json

在我的webpack.config.js中,我设置为我的React应用程序使用jsx-loader这样

entry: {
   app: "./app/index"
},
module: {
   loaders: [
        {
             test: /\.jsx$/,
             loader: 'jsx-loader?insertPragma=React.DOM&harmony',
     }
  ]
},
resolve: {
 extensions: ['', '.js', '.jsx']
}

这允许我要求以扩展名.jsx结尾的文件。例如,在/app/index.jsx中我需要/app/components/checkout.jsx来执行

 var Checkout = require('./components/Checkout')

/app/components/checkout.jsx内,我需要按钮

var Button = require('./components/Button')

所以当我需要index.jsx中的Checkout时,它会毫无问题地处理Button的要求。

然而,从app / test / test.js,我做

var Checkout = require('../components/Checkout')

并且webpack找不到Checkout组件。当我在webpack dev服务器中查看测试时,它没有显示查找.jsx文件扩展名。它搜索了

 app/components/Checkout
 app/components/Checkout.webpack.js
 app/components/Checkout.web.js
 app/components/Checkout.js
 app/components/Checkout.json

因此,我尝试使用内联jsx-loader

 var Checkout = require(jsx-loader!'../components/Checkout')
从测试目录

,webpack现在可以找到该文件,但它会抛出一个错误,说它无法解析Checkout requires的Button。换句话说,当我在require文件夹中使用app/test时,整个依赖关系链将被抛出不同步状态。

如何更改我的webpack.config.js以便能够在我的测试中使用此目录结构来要求应用程序文件,或者更一般地说,如何配置webpack以在测试中需要应用程序文件?

更新

项目结构

/app
  /test/test.js
  /index.jsx
  /components/checkout.jsx (and button.jsx)
/dist
/node_modules
package.json
webpack.config.js

整个webpack配置

var webpack = require('webpack');
module.exports = {
    context: __dirname + "/app",
    entry: {
      vendors: ["d3", "jquery"],
      app: "index"
      // app: "./app/index"

      },
    output: {
        path: './dist',
        filename: 'bundle.js', //this is the default name, so you can skip it
        //at this directory our bundle file will be available
        //make sure port 8090 is used when launching webpack-dev-server
        publicPath: 'http://localhost:8090/assets/'
    },

    externals: {
        //don't bundle the 'react' npm package with our bundle.js
        //but get it from a global 'React' variable

        'react': 'React'
        // 'd3': 'd3'
    },
    resolve: {
        modulesDirectories: ['app', 'node_modules'],
        extensions: ['', '.js', '.jsx'],
        resolveLoader: { fallback: __dirname + "/node_modules" },
        root: ['/app', '/test']
    },
    module: {
        loaders: [
            {
              test: /\.jsx$/, 
              loader: 'jsx-loader?insertPragma=React.DOM&harmony',
            }
        ]
    },

    plugins: [
    // definePlugin,
    new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js')

    ]
}

4 个答案:

答案 0 :(得分:3)

一种可能的解决方案是始终需要文件扩展名:

var Checkout = require('./components/Checkout.jsx')

答案 1 :(得分:3)

我想这可能是设置"测试"作为根目录。但是,直到你分享你的代码还不清楚。你能给我一个GitHub回购链接吗?

答案 2 :(得分:3)

我发现你正在使用和声参数,我可以假设你正在使用,es6?

如果是这样我之前遇到过这个问题,对我来说问题就是那些被添加的文件,如es6而没有变换,由jsx-loader / babel-loader添加到es5。

所以我需要添加:

preLoaders: [{
    test: [/\.jsx$/, /\.js$/],
    include: // modules here
    loaders: ['babel-loader?optional[]=runtime']
}]

然后它不能解释为什么这只会导致您的测试失败。也许你可以详细说明你运行测试时运行的是什么 但是现在我仍然假设您使用es6,

如果您不是上述情况,请尝试安装本地版本的webpack,并在您的本地目录中查找,也可以在您的应用文件夹中查找

(resolveLoader: { root: path.join(__dirname, "node_modules") })

希望这会有所帮助

编辑:ps看你的配置,resolveLoader不应该是你的决心的一部分,在我使用的另一个webpack设置中,我有以下设置 解决:

resolve: {
  extensions: ['', '.js', '.jsx', '.json'],
  modulesDirectories: ['node_modules', 'node_modules/vl_tooling/node_modules']
},
resolveLoader: {
  modulesDirectories: ['node_modules', 'node_modules/vl_tooling/node_modules']
},

答案 3 :(得分:1)

我设置了单独的gulp任务来运行React测试,也许你可以重用这个想法:

karma.js

var karma = require('gulp-karma'),
  _ = require('lodash'),
  Promise = require('bluebird'),
  plumber = require('gulp-plumber'),
  path = require('path'),
  webpack = require('gulp-webpack'),
  named = require('vinyl-named');

module.exports = function (gulp, options) {
  var root = path.join(options.cwd, 'app'),
    extensions = ['', '.js', '.jsx'],
    modulesDirectories = ['node_modules'];

  gulp.task('karma', ['karma:build'], function () {
    return runAllTests(gulp, options);
  });

  gulp.task('karma:build', function() {
    var optionsForTests = _.merge({
      ignore: ['**/node_modules/**']
    }, options);

    return gulp.src(['**/__tests__/*.js'], optionsForTests).
      pipe(named(function(file){
        // name file bundle.js
        return 'bundle';
      })).
      pipe(webpack({
        module: {
          loaders: [
              // runtime option adds Object.assign support
              { test: /\.(js|jsx)$/, loader: 'babel-loader?optional[]=runtime', exclude: /node_modules/},
              { test: /\.(sass|scss)$/, loader: 'css-loader!sass-loader'},
              { test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/, loader: 'url-loader'},
              { test: /\.(ttf|eot)$/, loader: 'file-loader'},
              { test: /sinon.*\.js$/, loader: 'imports?define=>false' } // hack due to https://github.com/webpack/webpack/issues/304
          ]
        },
        resolve: {
          root: root,
          extensions: extensions,
          modulesDirectories: modulesDirectories
        }
      })).
      pipe(gulp.dest('test-build'));
  })

}

function runAllTests(gulp, options) {
  var optionsForTests = _.merge({
    ignore: ['**/node_modules/**']
  }, options);

  return new Promise(function (resolve, reject) {
    var karmaConfig = path.join(path.resolve(__dirname, '..'), 'karma.conf.js');

    // shim Prototype.function.bind in PhantomJS 1.x
    var testFiles = [
      'node_modules/es5-shim/es5-shim.min.js',
      'node_modules/es5-shim/es5-sham.min.js',
      'test-build/bundle.js'];

    gulp.src(testFiles).
      pipe(plumber({
        errorHandler: function (error) {
          console.log(error);
          this.emit('end');
        }
      })).
      pipe(karma({
        configFile: karmaConfig,
        action: 'run'
      })).
      on('end', function () { resolve(); });
  });
}

Gulp文件:

var gulp = require('gulp');
var auctionataBuild = require('auctionata-build');
var path = require('path');

auctionataBuild.tasks.karma(gulp, {
  cwd: path.resolve(__dirname)
});

从终端运行:

 gulp karma