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')
]
}
答案 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