如何使用webpack的笑话?
我使用webpack来开发一个React组件。 这是一个简单的版本:
'use strict'; require('./MyComponent.less'); var React = require('react'); var MyComponent = React.createClass({ render() { return ( <div className="my-component"> Hello World </div> ); } }); module.exports = MyComponent;
现在,我想用jest来testing这个组件。 这里是我的package.json
的相关位:
"scripts": { "test": "jest" }, "jest": { "rootDir": ".", "testDirectoryName": "tests", "scriptPreprocessor": "<rootDir>/node_modules/babel-jest", "unmockedModulePathPatterns": [ "react" ] }
运行npm test
,出现以下错误:
SyntaxError:/Users/mishamoroshko/react-component/src/tests/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.less:Unexpected令牌非法
看起来webpack需要先处理require('./MyComponent.less')
然后才能运行testing。
我想知道是否需要使用像jest-webpack这样的东西 。 如果是的话,有没有办法指定多个scriptPreprocessor
? (注意我已经使用了babel-jest
)
我结束了以下黑客:
// package.json "jest": { "scriptPreprocessor": "<rootDir>/jest-script-preprocessor", ... } // jest-script-preprocessor.js var babelJest = require("babel-jest"); module.exports = { process: function(src, filename) { return babelJest.process(src, filename) .replace(/^require.*\.less.*;$/gm, ''); } };
但是,我仍然想知道什么是正确的解决scheme。
我发现忽略所需模块的最干净的解决scheme是使用moduleNameMapperconfiguration (工作在最新版本0.9.2)
文档很难遵循。 我希望以下将有所帮助。
将moduleNameMapper键添加到你的packages.jsonconfiguration中。 项目的关键字应该是所需string的正则expression式。 “.less”文件示例:
"moduleNameMapper": { "^.*[.](less|LESS)$": "EmptyModule" },
将EmptyModule.js添加到根文件夹中:
/** * @providesModule EmptyModule */ module.exports = '';
这个注释很重要,因为moduleNameMapper使用EmptyModule作为这个模块的别名( 阅读更多有关providesModule的内容 )。
现在每个需要引用的匹配正则expression式将被replace为一个空string。
如果您使用带有“js”文件的moduleFileExtensionsconfiguration,那么请确保您还将EmptyModule添加到“unmockedModulePathPatterns”中。
这里是我结束了的笑话configuration:
"jest": { "scriptPreprocessor": "<rootDir>/node_modules/babel-jest", "moduleFileExtensions": ["js", "json","jsx" ], "moduleNameMapper": { "^.*[.](jpg|JPG|gif|GIF|png|PNG|less|LESS|css|CSS)$": "EmptyModule" }, "preprocessorIgnorePatterns": [ "/node_modules/" ], "unmockedModulePathPatterns": [ "<rootDir>/node_modules/react", "<rootDir>/node_modules/react-dom", "<rootDir>/node_modules/react-addons-test-utils", "<rootDir>/EmptyModule.js" ] }
我最近发布了可能有帮助的Jestpack 。 它首先用Webpack构build你的testing文件,所以任何自定义的模块parsing/加载器/插件等都可以正常工作,并最终得到JavaScript。 然后为Jest提供一个定制的模块加载器,它可以理解Webpack模块的运行时间。
我发现使用Jest的moduleNameMapper
configuration更简单。
// package.json "jest": { "moduleNameMapper": { "^.+\\.scss$": "<rootDir>/scripts/mocks/style-mock.js" } } // style-mock.js module.exports = {};
我认为一个不太冒险的解决scheme是将你的预处理器封装在一个与JavaScript文件相匹配的文件名中:
if (filename.match(/\.jsx?$/)) { return babelJest.process(src, filename); } else { return ''; }
即使您没有在require行中明确设置扩展名,并且不需要源代码中的正则expression式replace,也可以工作。
我遇到过类似的问题
import React, { PropTypes, Component } from 'react'; import styles from './ContactPage.css'; import withStyles from '../../decorators/withStyles'; @withStyles(styles) class ContactPage extends Component {
对于运行Jest我有两个问题:
- 导入
.css
- 应用装饰
@withStyles
(TypeError: <...> (0 , _appDecoratorsWithStyles2.default)(...) is not a function
)
第一个是通过在脚本预处理器中嘲笑.css
本身来解决的。
第二个解决方法是使用unmockedModulePathPatterns
将装饰器从automocking中unmockedModulePathPatterns
module.exports = { process: function (src, filename) { ... if (filename.match(/\.css$/)) src = ''; ... babel.transform(src, ... } }
基于https://github.com/babel/babel-jest/blob/77a24a71ae2291af64f51a237b2a9146fa38b136/index.js的示例;
还要注意:当你使用jest预处理器的时候,你应该清理caching:
$ rm node_modules/jest-cli/.haste_cache -r
从Misha的回应中获得灵感,我创build了一个NPM包,解决了这个问题,同时处理了我遇到的几个场景:
的WebPack -巴贝尔,笑话
希望这可以节省下一个人几个小时。
如果你使用的是babel,你可以在babel转换过程中使用类似https://github.com/Shyp/babel-plugin-import-noop的方式;.babelrc
不需要的input,并configuration你的.babelrc
test
来使用插件。 :
{ "env": { "development": { ... }, "test": { "presets": [ ... ], "plugins": [ ["import-noop", { "extensions": ["scss", "css"] }] ] } } }
Webpack是一个很好的工具,但是我不需要用我的Jestunit testing来testing它的行为,并且在运行unit testing之前添加一个webpack构build只会减慢这个过程。 教科书的答案是使用"moduleNameMapper"
选项来模拟非代码依赖关系
https://facebook.github.io/jest/docs/webpack.html#handling-static-assets
来自Jest文档 :
// in terminal, add new dependency: identity-obj-proxy npm install --save-dev identity-obj-proxy // package.json (for CSS Modules) { "jest": { "moduleNameMapper": { "\\.(css|less)$": "identity-obj-proxy" } } }
上面的代码片段将所有.less
文件路由到新的依赖关系identity-obj-proxy
,这将在调用时返回一个带有类名的string,例如styles.styleName
'styleName'
。