Closed creeperyang closed 7 years ago
babel@6.x
的require
加载模块的问题[babel-node
之require
]问题详细描述:
"scripts": {
"clean": "babel-node --eval \"require('./tools/clean')().catch(err => console.log(err.stack))\""
}
npm run clean
require('./tools/clean')().catch(function (err) {
^
TypeError: object is not a function
'./tools/clean'.js
的内容:
const clean = async () => {
await del(['build/*', '!build/.git'], { dot: true });
await fs.mkdir('build');
};
export default clean;
比较奇怪,报错信息竟然是 require('./tools/clean')
不是函数。我们改下npm run clean
的内容,直接输出 require('./tools/clean')
:
{ __esModule: true, default: [Function] }
OK,似乎比较清晰了: require('./tools/clean')
返回的我们不是需要的clean
函数,而是包裹一层的{default: clean function}
。
那么为什么babel-node
的require
不是直接输出export default
的值呢?
export default x
会被babel
编译为exports.default = x
;require
时加载到的就是{ __esModule: true, default: x}
,所以出现上述错误;babel
编译import x from 'x'
会处理成(0, _x2.default)
,可以正确获取default
。既然如此,尝试改为"clean": "babel-node --eval \"import clean from './tools/clean'; clean().catch(err => console.log(err.stack))\""
,报错:
SyntaxError: [eval]: Modules aren't supported in the REPL
> 1 | import clean from './tools/clean'; clean().catch(err => console.log(err.stack))
好吧,看来我们只能手动去获取default
再执行了。
babel@6.x
的编译配置问题问题背景:babel编译koa插件时希望保留generator不要编译。
"presets": ["es2015"]
然而preset中并不能单独disable某个plugin,详见https://phabricator.babeljs.io/T3016。
因此比较挫/比较快速的一个变通就是手动去配置每个plugin。
react-transform-hmr
的state
变动不更新问题缘起:更新上面所说的React Hot Loading已经过时了,开发者也宣布已经停止维护,现在有一个更强大的babel plugin: React Transform来代替他...
想紧跟时代,用高大上的react-transform
,然后,倒在了state
的问题上。详见https://github.com/gaearon/react-transform-hmr/issues/41
然后我傻傻地去改this.state
,满心期望transform能够成功。然而,浏览器log一切正常,页面内容却始终不变...一次,两次,三次,换个姿势再来,嗯,就是不起作用——这让我一度怀疑人生,为什么按作者的一步步来,我就是不成功。
google之,没找到答案,试验了千万种道路,最后只能一步一步调试,到最后发现react-proxy
这个库更新得到新的ReactComponent时,并没有去复制最新的state。
What the hell! 当我满怀悲愤地准备提issue时,发现不仅有了提了相同的问题,甚至已经9天前有人提了pr修复这个问题,更加泪流满面 :sob: 。
一个深刻的道理:搜索真的是一门技术,先到github项目上搜,搜issue请把:is open
去掉。最后的最后,才是自己源码调试...
另:为什么我一上来碰到的就是corner case,发现以上答案后,我偷偷改了改render函数,哇,真的浏览器无刷新更新了诶!!!
react-transform-catch-errors
]()的not work的问题场景:配置好react-transform-catch-errors
后,特意在render中加一行<h2>error
。满心欢喜等待redbox
来个大大的错误显示,结果是在控制台输出错误并重刷页面了。
心情不好了。吸取上面的教训,直接到repo到issues去找找看。功夫不负有心人,十几分钟后找到了答案:https://github.com/gaearon/react-transform-catch-errors/issues/17
很简单,语法错误不被webpack-dev-server
支持。
What you want is unrelated to this transform.
Syntax error overlay is a feature of a different project called webpack-hot-middleware. It's a replacement for webpack-dev-server.
Babel
转换async
函数的参数问题问题的核心是async
函数转换后没有正确处理默认参数。代码如下:
const mergeImage = async (sourceImgPaths, mergedImgPath, arrangement = 'smart', options = {}) => {
console.log(sourceImgPaths, mergedImgPath, arrangement, options);
}
转换后:
var mergeImage = function () {
var ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(sourceImgPaths, mergedImgPath) {
var arrangement = _arguments.length <= 2 || _arguments[2] === undefined ? 'smart' : _arguments[2];
var options = _arguments.length <= 3 || _arguments[3] === undefined ? {} : _arguments[3];
var margin, images, rects, pack, mergedImage, batch;
return regeneratorRuntime.wrap(function _callee$(_context) {
// ...
很明显,arrangement
和options
的转换完全错误(正确的应该是类似var arrangement = arguments.length <= 2
)。
查看下_arguments
到底什么东西?
function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.mergeImage = undefined;
var _arguments = arguments;
// ...
var mergeImage = function () {
:joy: :joy: :joy:
至此,arrangement
和options
总是取不到正确值的原因已找到,但更深入一步,Babel
为什么这么转换需要继续查找。
目前环境:
"babel-cli": "^6.5.1",
"babel-core": "^6.5.1",
"babel-loader": "^6.2.2",
"babel-preset-es2015": "^6.3.13",
"babel-preset-stage-0": "^6.3.13",
暂时解决方法:
async
和arrow function
不混用时,babel是可以正确处理的。
async function mergeImage() {
}
istanbul
+ jasmine
+babel-node
测试代码无法收集 coverage informationistanbul
之前用的并不太多,现在配合babel-node
,jasmine
做覆盖测试,各种问题就来了。
执行"test-cov": "node_modules/.bin/babel-node node_modules/istanbul/lib/cli cover test/run.js"
,输出如下:
Transformation error; return original code
{ [Error: Line 239: Unexpected token] lineNumber: 239, description: 'Unexpected token', index: 7963 }
Transformation error; return original code
{ [Error: Line 1: Unexpected token] lineNumber: 1, description: 'Unexpected token', index: 15 }
...
...
...
Executed 18 of 18 specs SUCCESS in 8 secs.
No coverage information was collected, exit without writing coverage information
Transformation error
(但单元测试是正确执行完);coverage information
。针对1并没有找到什么好的处理方法,跟踪istanbul
,程序执行到Module.runMain(cmd, null, true);
时依然正常。
针对2,https://github.com/gotwarlost/istanbul/issues/262 里讨论比较多,然后各种尝试,最后感谢https://github.com/suhasdeshpande/calendar-library/commit/6720509dddfa0192650283648d7917bb46b335a5,更新istanbul
到1.x
(目前还在alpha阶段,但作为测试工具,现在就可以用起)版本即可解决。
sass-loader
报错Invalid CSS after "xxxx": expected 1 selector or at-rule
真实情况下,报错详细信息:
Module build failed:
.inject-shadow {
^
Invalid CSS after "...load the styles": expected 1 selector or at-rule, was "content = requi..."
in /Users/creeper/work/projects/FlightBooking/app/pages/index/inject.scss (line 1, column 1)
@ ./app/pages/index/inject.scss 4:14-776 13:2-17:4 14:20-782
错误信息是指无效的css代码,然而检查过后,inject.scss
里显然都是合法的css代码,也必然是合法的scss代码了。
在sass-loader
repo中找到一个类似的issue https://github.com/jtangelder/sass-loader/issues/187,虽然报错信息类似,但该issue中,文件代码是sass格式的,不是合法的scss,报错信息是比较好理解的。
对照我的问题,再次check我的loader,有个思路:是不是被sass-loader
接受的并不是inject.scss
原本的内容,所以有非法代码?
const loaders = [{
test: new RegExp(MODULE_VIEWER_SETTING.injectStyleName + '$'),
loader: 'css!postcss-loader!sass-loader'
}, {
test: /\.scss$/,
exclude: [/app\/styles\/\S+\.scss$/],
loader: sassLoader
},
以上是相关的loader定义。loader的本意是scss
文件用通用的sassLoader
处理,但inject.scss
特殊处理。一想,是不是inject.scss
被处理了两次,第一次产出的代码不再是合法的scss-loader
输入?
测试,把第二个loader的exclude中显式排除inject.scss
,果然可以正确运行。
git commit
的迷之报错git add .
git commit -m 'message'
sh: standard: command not found
git commit
失败,给出的原因是sh: standard: command not found
。完全找不到思路,google之,依然没思路。
看信息是sh
的锅,但完全没道理。尝试git commit -h
,可以正常显示help。
最后,在lyn老司机提示下,才发现是commit hook
的锅。commit hook
会执行standard
,然而我并没有装这个依赖...
css-loader
怎么在file-loader/url-loader
的帮助下处理静态资源?一个常见的场景:怎么只让css中的url正确映射图片而不去重新生成新的图片?
// source
static/
css/a.css (url('../images/x.png'))
images/x.png
// dest
static/
css-compiled/a.css (url('../images/x.png'))
images/x.png
默认情况下,css-loader
配合file-loader/url-loader
会在static/css-compiled
下生成对应的x-hash.png
,并且改变css为url(x-hash.png)
。
怎么配置来达成题目的要求?
file-loader@0.9
新支持了emitFile=false
选项来禁止生成新的资源文件。同时,配置file-loader/url-loader
的name来配合。
{
test: /\.(gif|png|jpe?g)$/i,
loader: [
'file?emitFile=false&name=../images/[name].[ext]',
'url?limit=1000&name=../images/[name].[ext]'
].join('!')
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader : 'file?emitFile=false&name=../fonts/[name].[ext]'
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('css-loader!postcss-loader')
}
参考资料:
babel-preset-es2015
并不包含Object.assign
在某vivo手机上碰到一个bug,查看报错信息是undefined is not a function
—— 很经典的报错。
把报错行数周围的代码看一遍,并没有哪里不对。
const titleErrMsg = value && verifyTitle(value)
this.setState({
deliver: Object.assign({}, this.state.delivery, {
invList: this.state.delivery.invList.map((inv, i) => {
// xxxx
})
})
})
而这段代码可疑之处只有verifyTitle
Array.prototype.map
Object.assign
这3个函数,一一测试,最后发现Object.assign
是undefined
。
查看webpack
配置,用了es2015, react
的配置,查看编译后代码,的确还保留着Object.assign
...
正确的配置:
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel',
query: {
presets: ['react','es2015'],
plugins: ['transform-object-assign']
}
}
Babel 6
生态一个babel的简介,帮助理清整个Babel 6
生态。
内容已转移到 #25
参考:
webpack@3
警告 There are multiple modules with names that only differ in casing.
WARNING in ./node_modules/react-toolbox/lib/Link/index.js
There are multiple modules with names that only differ in casing.
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
Use equal casing. Compare these module identifiers:
* /Users/creeper/work/waves/lottie_admin/node_modules/react-toolbox/lib/Link/index.js
Used by 1 module(s), i. e.
/Users/creeper/work/waves/lottie_admin/node_modules/babel-loader/lib/index.js??ref--0!/Users/creeper/work/waves/lottie_admin/src/components/Header/index.js
* /Users/creeper/work/waves/lottie_admin/node_modules/react-toolbox/lib/link/index.js
Used by 1 module(s), i. e.
/Users/creeper/work/waves/lottie_admin/node_modules/react-toolbox/lib/navigation/index.js
经过排查,引起问题的为这样一行代码:
import Link from 'react-toolbox/lib/Link'
但实际目录是这样的:node_modules/react-toolbox/lib/link
,所以请注意大小写。
这里纪录了前端工具使用和工作流的问题,包括但不限于编译打包,版本管理,代码测试,工程化等等。
关键词:
Babel
Webpack
git
等等。强调下,除非特殊说明,否则这里的
babel
,babel-cli
都是6.x
版本的。