【问题标题】:create a test entry point in webpack react application在 webpack react 应用程序中创建一个测试入口点
【发布时间】:2015-10-16 09:30:27
【问题描述】:

tldr:我可以 require 一切使应用程序运行,但如果我在测试中 require 模块(在应用程序中 - 请参阅下面的目录结构)文件,整个依赖链就中断了。

我在require-ing 下面的 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 中,我设置为像这样将 jsx-loader 用于我的 React 应用程序

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 开发服务器中查看测试时,它没有显示 .jsx 文件扩展名已被查找。它搜索了

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

因此,我尝试像这样使用jsx-loaderinline

 var Checkout = require(jsx-loader!'../components/Checkout')

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

如何更改我的 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')

    ]
}

【问题讨论】:

  • 你是如何设置 webpack 配置来运行测试的,它是相同的还是与 main 不同的?在我的设置中,我使用 2 个不同的配置来运行开发构建和反应测试。类似问题的解决方法是在 webpack 中添加 resolve: { extensions: ['', '.js', '.jsx'] } 以运行测试。
  • @EugeneSafronov 现在我在项目的顶层只有一个 webpack 配置。我将它的副本放在 OP 的更新部分,以及有关项目结构的更多详细信息。我考虑过使用第二个配置进行测试,但不知道该放在哪里或如何配置它。你能提供一些相关信息吗?
  • 您的加载程序中没有缺少include: __dirname 吗?也可以试试:/\.jsx?$/
  • @knowbody 这些建议都不能解决问题。
  • @Leahcim 我会在我的笔记本电脑上查看它

标签: reactjs webpack


【解决方案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

【讨论】:

    【解决方案2】:

    我看到你正在使用和声参数,我可以假设你正在使用 es6 吗?

    如果是这样,我之前遇到过这个问题,对我来说,问题是通过 jsx-loader / babel-loader 将文件添加为 es6 而不进行beeing 转换为 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']
    },
    

    【讨论】:

    • 我使用的是 jsx 但不是 es6。在你回答的最后,你把“modulesDirectories”放在“resolve”和“resolveLoader”中。两者都应该吗?
    【解决方案3】:

    我猜这可能是因为将“test”设置为根目录。但在您分享代码之前还不清楚。能给个GitHub repo之类的链接吗?

    【讨论】:

    • 测试入口点已被取出(请参阅对 OP 的更新)。该项目不在 github 上。
    • 我在说这个:root: ['/app', '/test'],它仍然存在于你的 webpack 配置中
    【解决方案4】:

    一种可能的解决方案是总是要求文件扩展名:

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

    【讨论】:

    • 这允许我特别需要该组件,但是在运行测试时它说 JSX 令牌(即<)是 'unexpected' 。该应用程序仍然可以正常工作,只是测试的问题。正如我在 OP ` 中的 OP , when I use the require from within the app/test folder, the whole dependency chain is thrown out of sync. 中所述,所以我认为问题与我的 webpack.config.js 文件有关,我在 OP 中显示了相关位
    猜你喜欢
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多