Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端工具(util)或自动化(workflow)的问题 #13

Closed
creeperyang opened this issue Dec 15, 2015 · 11 comments
Closed

前端工具(util)或自动化(workflow)的问题 #13

creeperyang opened this issue Dec 15, 2015 · 11 comments

Comments

@creeperyang
Copy link
Owner

creeperyang commented Dec 15, 2015

这里纪录了前端工具使用和工作流的问题,包括但不限于编译打包,版本管理,代码测试,工程化等等。

关键词:Babel Webpack git等等。

强调下,除非特殊说明,否则这里的babel, babel-cli都是6.x版本的。

@creeperyang
Copy link
Owner Author

1. [email protected]require加载模块的问题[babel-noderequire

问题详细描述:

"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-noderequire不是直接输出export default的值呢?

  1. export default x会被babel编译为exports.default = x
  2. 默认require时加载到的就是{ __esModule: true, default: x},所以出现上述错误;
  3. 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再执行了。

2. [email protected]的编译配置问题

问题背景:babel编译koa插件时希望保留generator不要编译。

"presets": ["es2015"]

然而preset中并不能单独disable某个plugin,详见https://phabricator.babeljs.io/T3016。

因此比较挫/比较快速的一个变通就是手动去配置每个plugin。

@creeperyang
Copy link
Owner Author

3. react-transform-hmrstate变动不更新问题

缘起:更新上面所说的React Hot Loading已经过时了,开发者也宣布已经停止维护,现在有一个更强大的babel plugin: React Transform来代替他...

想紧跟时代,用高大上的react-transform,然后,倒在了state的问题上。详见gaearon/react-transform-hmr#41

然后我傻傻地去改this.state,满心期望transform能够成功。然而,浏览器log一切正常,页面内容却始终不变...一次,两次,三次,换个姿势再来,嗯,就是不起作用——这让我一度怀疑人生,为什么按作者的一步步来,我就是不成功。

google之,没找到答案,试验了千万种道路,最后只能一步一步调试,到最后发现react-proxy这个库更新得到新的ReactComponent时,并没有去复制最新的state。

What the hell! 当我满怀悲愤地准备提issue时,发现不仅有了提了相同的问题,甚至已经9天前有人提了pr修复这个问题,更加泪流满面 😭 。

一个深刻的道理:搜索真的是一门技术,先到github项目上搜,搜issue请把:is open去掉。最后的最后,才是自己源码调试...

另:为什么我一上来碰到的就是corner case,发现以上答案后,我偷偷改了改render函数,哇,真的浏览器无刷新更新了诶!!!

@creeperyang creeperyang changed the title Questions about Babel & ES-Next Questions about Babel, ES-Next and Webpack Feb 2, 2016
@creeperyang
Copy link
Owner Author

4. react-transform-catch-errors的not work的问题

场景:配置好react-transform-catch-errors后,特意在render中加一行<h2>error。满心欢喜等待redbox来个大大的错误显示,结果是在控制台输出错误并重刷页面了。

心情不好了。吸取上面的教训,直接到repo到issues去找找看。功夫不负有心人,十几分钟后找到了答案:gaearon/react-transform-catch-errors#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.

@creeperyang
Copy link
Owner Author

5. 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) {
        // ...

很明显,arrangementoptions的转换完全错误(正确的应该是类似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 () {

😂 😂 😂

至此,arrangementoptions总是取不到正确值的原因已找到,但更深入一步,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",

暂时解决方法:

asyncarrow function不混用时,babel是可以正确处理的。

async function mergeImage() {
}

@creeperyang creeperyang changed the title Questions about Babel, ES-Next and Webpack Questions about front-end workflow, tools and test (Babel/Webpack/istanbul/jasmine ...) Feb 17, 2016
@creeperyang
Copy link
Owner Author

6. istanbul + jasminebabel-node测试代码无法收集 coverage information

istanbul之前用的并不太多,现在配合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
  1. 报错Transformation error(但单元测试是正确执行完);
  2. 没有coverage information

针对1并没有找到什么好的处理方法,跟踪istanbul,程序执行到Module.runMain(cmd, null, true);时依然正常。

针对2gotwarlost/istanbul#262 里讨论比较多,然后各种尝试,最后感谢https://github.com/suhasdeshpande/calendar-library/commit/6720509dddfa0192650283648d7917bb46b335a5,更新`istanbul`到`1.x`(目前还在alpha阶段,但作为测试工具,现在就可以用起)版本即可解决。

@creeperyang
Copy link
Owner Author

7. webpack中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,果然可以正确运行。

@creeperyang
Copy link
Owner Author

8. 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,然而我并没有装这个依赖...

@creeperyang
Copy link
Owner Author

9. 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)

怎么配置来达成题目的要求?

[email protected]新支持了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')
                }

参考资料:

  1. Question: Suggestion: Webpack hard to build desired structure webpack/webpack#1370
  2. Add explanation webpack-contrib/css-loader#1

@creeperyang
Copy link
Owner Author

10. 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.assignundefined

查看webpack配置,用了es2015, react的配置,查看编译后代码,的确还保留着Object.assign...


正确的配置:

               {
                    test: /\.jsx?$/,
                    exclude: /(node_modules|bower_components)/,
                    loader: 'babel',
                    query: {
                        presets: ['react','es2015'],
                        plugins: ['transform-object-assign']
                    }
                }

@creeperyang creeperyang changed the title Questions about front-end workflow, tools and test (Babel/Webpack/istanbul/jasmine ...) Babel/Webpack/istanbul等等的使用问题 Oct 28, 2016
@creeperyang creeperyang added Q&A and removed note labels Oct 28, 2016
@creeperyang creeperyang changed the title Babel/Webpack/istanbul等等的使用问题 babel/webpack/istanbul等等的使用问题 Oct 28, 2016
@creeperyang creeperyang removed the Q&A label Dec 9, 2016
@creeperyang creeperyang changed the title babel/webpack/istanbul等等的使用问题 前端工具(util)或自动化(workflow)的问题 Dec 9, 2016
@creeperyang
Copy link
Owner Author

creeperyang commented Feb 15, 2017

了解Babel 6生态

一个babel的简介,帮助理清整个Babel 6生态。

内容已转移到 #25

参考:

Clearing up the Babel 6 Ecosystem
6.0.0 Released

@creeperyang
Copy link
Owner Author

11. 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,所以请注意大小写。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant