liaoyf的博客

一分耕耘一分收获


  • 首页

  • 标签

  • 归档

  • 关于

  • 搜索

2018年学习计划(yarn篇)

发表于 2018-08-13 | 阅读次数

这里只记一些感觉比较重要的内容。

什么是yarn

Yarn 是 Facebook, Google, Exponent 和 Tilde 开发的一款新的 JavaScript 包管理工具。它并没有试图完全取代 npm。Yarn 同样是一个从 npm 注册源获取模块的新的 CLI 客户端。注册的方式不会有任何变化 —— 你同样可以正常获取与发布包。它存在的目的是解决团队在使用 npm 面临的少数问题。当然,在 Node 版本断更替中,Npm 本身也在积极更新。

npm 与 yarn 常用命令对比

Npm Yarn 功能描述
npm install(npm i) yarn install(yarn) 根据 package.json 安装所有依赖
npm i –save [package] yarn add [package] 添加依赖包
npm i –save-dev [package] yarn add [package] –dev 添加依赖包至 devDependencies
npm i -g [package] yarn global add [package] 进行全局安装依赖包
npm update –save yarn upgrade [package] 升级依赖包
npm uninstall [package] yarn remove [package] 移除依赖包

如何探查 npm 包

如果你想从cli打开模块的主页,你可以这样做:

1
npm home axios

要检查未决的问题或公开的路线图(如果有的话),你可以试试这个:

1
npm bugs axios

另外,如果你只是想检查模块的 git 仓库,请输入:

1
npm repo axios

几个感觉有用的yarn命令

  • yarn add -D/–dev

安装到devDependencies依赖中

  • yarn add

安装到dependencies依赖中

  • yarn add -E/–exact

安装包的精确版本,默认是安装包的主要版本里的最新版本。 比如说, yarn add foo@1.2.3 会接受 1.9.1 版,但是 yarn add foo@1.2.3 –exact 只会接受 1.2.3 版。

  • yarn cache dir

显示yarn缓存的目录,我电脑默认:C:\Users\Administrator\AppData\Local\Yarn\Cache\v2

通过yarn config set cache-folder <path>改变缓存目录,不然放在C盘太占空间了。通过yarn cache clean清空掉。

检测包完整性

  • yarn check

验证当前项目 package.json 里的依赖版本和 yarn 的 lock 文件是否匹配。

  • yarn check –integrity

验证当前项目 package.json 里包内容的版本和 hash 值是否与 yarn 的 lock 文件一致。 这有助于验证包依赖没有更改。

  • yarn check –verify-tree

检查node_modules下的dependencies依赖包是否存在和版本是否正确。

假设一个项目:package.json中依赖bootstrap3.x版本,假设:

  • 更改package.json中bootstrap版本改成4.x,分别运行以上三句命令:

    • yarn check:

      1
      2
      3
      error Lockfile does not contain pattern: "bootstrap@4.x"
      error "bootstrap" is wrong version: expected "4.1.3", got "3.3.7"
      error Found 2 errors.
- `yarn check --integrity`:

1
2
error Lockfile does not contain pattern: "bootstrap@4.x"
error Found 1 errors.
- `yarn check --verify-tree`:
1
2
error "bootstrap" is wrong version: expected "4.x", got "3.3.7"
error Found 1 errors.
如上结果,可以看出`--integrity`主要是判断`package.json`是否被手动改坏掉了,`--verify-tree`用于判断`node_modules`下是否已经根据`package.json`更新了版本。 > 个人感觉:应该可以在项目启动或打包前运行`yarn check --verify-tree`,因为这个速度比较快;在多人合作开发中可以告知其他开发者要手动运行`yarn`更新依赖版本了。
  • yarn create []

从一些以create-*开头的脚手架生成项目。比如:yarn create react-app my-app相当于yarn global add create-react-app && create-react-app my-app。

  • yarn help

查看命令帮助

  • yarn info []

查看某个包的描述。yarn info <package> version查看某个包的所有可用版本。

  • yarn install –flat

仅为某一个包安装一个确定版本,如果有不同版本依赖将会让你选择。它将会在在package.json文件增加resolutions字段。

  • yarn outdated [package…]

列出一个或多个程序包依赖项的版本信息。

  • yarn upgrade [package]… –latest|-L [–caret | –tilde | –exact] [–pattern]

--latest标识升级到最新版本。通过--caret、或--tilde指定使用什么类型的版本。比如:yarn upgrade --latest --caret升级boostrap: '3.x'到bootstrap: ^4.1.3。

参考

  • https://yarn.bootcss.com/docs/

2018年学习计划(npm篇)

发表于 2018-08-02 | 阅读次数

主要温习下npm知识,这篇不会很详细介绍npm的使用,而是记下认为有用的知识点。

阅读全文 »

Rollup(入门学习)

发表于 2018-08-01 | 阅读次数

概述

Rollup 是一个 JavaScript 模块打包器,Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。

阅读全文 »

前端调试技巧

发表于 2018-07-25 | 阅读次数

前端调试说简单也简单,说难也难,我们今天就以chrome浏览器为主,探究常用的调试技巧。

阅读全文 »

css-transforms-3d

发表于 2018-06-21 | 阅读次数

浏览器支持情况

2D Transforms

Chrome Safari Firefox Opera IE Android iOS
Any 3.1+ 3.5+ 10.5+ 9+ 4.1+ At least 4

3D Transforms

Chrome Safari Firefox Opera IE Android iOS
10+ 4+ 12+ none 10+ 4.1+ 5+

2D Transforms

  • scale(): 缩放元素,包括:font-size,padding,height,width。它还提供scaleX和scaleY速记函数。

  • skewX() and skewY(): 元素向左或者向右倾斜,这个没有skew函数。

  • translate(): 位移元素

  • rotate(): 顺时针翻转元素

  • matrix(): 矩阵,这个函数可能不是专门用手写的,但将所有转换合并为一个。

  • perspective(): 不会影响元素本身,但会影响后代元素3D变换的变换,从而使它们都具有一致的深度透视图。

3D Transforms

Perspective

要激活3D空间,元素必须要有透视。可以有两种方式使用:使用transform: perspective(600px)或者perspective: 600px。

perspective决定3D效果的强度的值。把它看作从观察者到物体的距离。值越大,距离越远,视觉效果越不强烈。perspective: 2000px;产生微妙的3D效果,就像我们通过双筒望远镜从远处观看物体一样。perspective: 100px;产生巨大的3D效果,就像一只看到巨大物体的小昆虫。

可以在子元素上使用perspective或者父级元素,但是,当用于多个元素时,转换后的元素不会按预期排列。如果跨不同位置的元素使用相同的变换,则每个元素都有自己的视点。为了解决这个问题,请使用perspective父元素的属性,以便每个孩子可以共享相同的3D空间。参考https://desandro.github.io/3dtransforms/examples/perspective-02-children.html

See the Pen css-3d-transforms-perspective by liaoyf (@liaoyf) on CodePen.

默认情况下,3D空间的视点位于中心。你可以用perspective-origin属性来改变视点的位置。

1
perspective-origin: 25% 75%;

3D Transform functions

  • rotateX( angle )
  • rotateY( angle )
  • rotateZ( angle )
  • translateZ( tz )
  • scaleZ( sz )

还有几个速记变换函数需要所有三个维度的值:

  • translate3d( tx, ty, tz )
  • scale3d( sx, sy, sz )
  • rotate3d( rx, ry, rz, angle )

这些foo3d()转换函数还具有在Safari中触发硬件加速的好处,如果您正在编写适用于iOS或Safari的生产准备CSS,请务必使用这些foo3d()函数以获得最佳的渲染性能。

react-native版本0.55搭建

发表于 2018-06-20 | 阅读次数

react-native开发流程

create-react-native-app方式

使用此方式无需安装编译器、xcode或者Android Studio等。

1
2
3
4
npm install -g create-react-nateive-app
create-react-native-app AwesomeProject
cd AwesomeProject
npm start

启动后,控制台会输出一个二维码,接下来,你需要使用手机安装Expo应用程序,然后使用二维码登录即可在访问,如果你修改代码,应该也会热更新。

用native code构建

在IOS上,需要安装一些必须软件:

1
2
3
4
5
6
brew install node
brew install watchman
npm install -g react-native-cli
react-native init AwesomeProject
cd AwesomeProject
react-native run-ios

使用Command + R刷新。

注意:Xcode版本必须要>=8

react-native run-ios报错

报错如下:

1
2
3
4
5
6
7
8
9
10
11
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=2):
Failed to install the requested application
An application bundle was not found at the provided path.
Provide a valid path to the desired application bundle.
Print: Entry, ":CFBundleIdentifier", Does Not Exist
/development/misc/react/AwesomeProject/node_modules/promise/lib/done.js:10
throw err;
^

Error: Command failed: /usr/libexec/PlistBuddy -c Print:CFBundleIdentifier build/Build/Products/Debug-iphonesimulator/AwesomeProject.app/Info.plist
Print: Entry, ":CFBundleIdentifier", Does Not Exist

泪崩。。。试用遍了网上大多数的解决方法均不行,浪费了好多宝贵时间,后来发现是xcode的版本问题,0.55版本要求xcode的版本要>= 8。

所以要更新xcode版本即可解决,记得更新完后重新react-native init项目。

结合antd-mobile使用

安装antd-mobile-rn:

1
yarn add antd-mobile-rn

使用:

1
2
3
4
5
6
7
8
9
10
11
import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import Button from 'antd-mobile-rn/lib/button';

class HelloWorldApp extends Component {
render() {
return <Button>Start</Button>;
}
}

AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);

更多坑请点击查看

调用原生模块

1
2
3
import { NativeModules } from 'react-native';
var CalendarManager = NativeModules.CalendarManager;
CalendarManager.addEvent('Birthday Party', '4 Privet Drive, Surrey');

详细介绍请点击查看

开发后安装问题

在真机上测试iOS应用需要一台Mac电脑,同时还需要注册一个Apple ID。如果你需要把应用发布到App Store,那么你还需要去苹果开发者网站购买一个开发者账户(在自己手机上测试则不用)

在真机上访问开发服务器(packager)

你可以在真机上访问开发服务器以快速测试和迭代。首先需要确保设备已使用usb连接至电脑,同时和电脑处在同一wifi网络内,然后在Xcode中选择你的设备作为编译目标(左上角运行按钮的右边),然后点击运行按钮即可。
如果你需要在真机上启用调试功能,则需要打开RCTWebSocketExecutor.m文件,然后将其中的”localhost”改为你的电脑的IP地址,最后启用开发者菜单中的”Debug JS Remotely”选项。

开发步骤:

  1. 使用xcode打开项目

  2. 使用USB链接手机,并和电脑处于统一wifi信号下

  3. 选择右上角为你的手机,然后点击三角形运行

  4. 输入电脑登录密码,之后软件会安装在你的手机上

  5. 由于软件不被信任,所以要在通用->设备管理->点击信任

提示:摇晃设备就可以打开开发者菜单。

发布应用

当你使用React Native做好一个漂亮的应用之后,一定跃跃欲试想要在App Store上发布了吧。发布的流程和其他iOS原生应用完全一样,除了以下一些注意事项。
在App Store上发布应用首先需要编译一个“发布版本”(release)的应用。具体的做法是在Xcode中选择Product -> Scheme -> Edit Scheme (cmd + <),然后选择Run选项卡,将Build Configuration设置为release。 Release版本的应用会自动禁用开发者菜单,同时也会将js文件和静态图片打包压缩后内置到包中,这样应用可以在本地读取而无需访问开发服务器(同时这样一来你也无法再调试,需要调试请将Buiid Configuration再改为debug)。
由于发布版本已经内置了js文件,因而也无法再通过开发服务器来实时更新。面向用户的热更新,请使用专门的热更新服务。
编译完成后,你就可以打包提交到TestFlight进行内测,或是提交到App Store进行发布。相关流程较为复杂,不熟悉原生应用发布流程的同学请自行搜索学习。

App Transport Security

App Transport Security(简称ATS)是iOS 9中新增的一项安全特性。在默认设置下,只允许HTTPS的请求,而所有HTTP的请求都会被拒绝。详情可参考这篇帖子。

使用react-native开发的可行性

根据Airbnb提供,具体参考:https://zhuanlan.zhihu.com/p/38288285?utm_source=com.alibaba.android.rimet&utm_medium=social:

优点

  • 跨平台 (只有 0.2% 的平台特定代码)
  • 统一的设计语言,同时还能为不同平台提供不同设计
  • React 的 scale 很好,生命周期比原生简单,声明式很好
  • 迭代速度快(主要是 hot reloading 很快)
  • 大量基础设施的投入值得(网络、国际化、复杂动画、设备信息、用户信息等等都是通过一个桥把原生 api 暴露给 RN 的。)
  • 同时他们在这里也指出:他们并不相信在一个已有 app 上集成 RN 是一件简单事儿,必须要大量且持续地投入基础设施才行(说好的「满意的地方」呢)
  • 性能 (尽管大家都担心但是其实基本没有问题)
  • 不过首次渲染比较慢,导致不适合用作启动屏、deeplink,也增加了可交互时间(TTI),另外掉帧不好 debug(说好的「满意的地方」呢)
  • Redux(好用,虽然废话太多)
  • 背后是原生,一些曾经不确定能不能做的功能(Shared element transitions、动画库 Lottie、网络层、核心基础设施)发现都能做
  • 静态分析(eslint,prettier,一些性能检测)
  • 动画
  • JS/React 的开源生态
  • Flexbox (via Yoga)
  • 有时候可以加上 Web 跨三端

缺点

  • RN 太不成熟
  • 需要 fork RN
  • JS 不行 (JS 没有类型不 scale,flow 不好用,TS 不好集成到 babel 和 metro)
  • 不好重构(JS 没有类型无法静态分析,重构引起的错误不能在编译时被捕捉到)
  • 咳,用我 FB 的新编译到 JS 语言大 ReasonML 啊……静态强类型 + 类型推断 + 自带不可变数据结构 + JS 友好语法 + 官方 React 支持,绝对 scale(咳扯远了
  • JSCore 在 iOS / Android 上不一致 (Android 上是 RN 自己 bundle 的),很难 debug 这种坑
  • RN 的开源库质量不行(因为太少人能精通所有平台了)
  • 做功能时要回去搞基础设施(因为有的基础设施可能还没暴露给 RN)
  • 奔溃监控(业内没方案,只能自己搞)
  • 原生桥太难写,另外 JS 的类型太难预料(和强类型语言 interop 时)
    -RN 运行时的初始化太慢
  • 首次渲染时间慢(需要从 主线程 -> JS -> Yoga -> 主线程)
  • 应用体积
  • 64 位 (因为 RN 不兼容的 issue 导致他们至今没法在 android 发布 64 位应用)
  • 手势(iOS 和 Android 的手势不好统一,虽然他们搞了 react-native-gesture-handler)
  • 长列表
  • 升级 RN 有的时候非常麻烦
  • Accessibility (RN 的有 bug,又要 fork)
  • 稀奇古怪的奔溃
  • 安卓上的应用实例序列化问题

个人观点

如果不需要开发那种非常复杂的功能,react-native社区提供的第三方库基本能满足开发需求;

jest测试工具学习(入门篇)

发表于 2018-06-19 | 阅读次数

使用匹配器

普通匹配器

  • toBe:测试值的方法是看是否精确匹配,相反的匹配器是.not.toBe;

  • toEqual: 递归检查对象或数组的每个字段

Truthiness

  • toBeNull

  • toBeUndefined

  • toBeDefine

  • toBeTruthy: 匹配任何 if 语句为真

  • toBeFalsy: 匹配任何 if 语句为假

数字

大多数的比较数字有等价的匹配器。

1
2
3
4
5
6
7
test('two plus two', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessOrEqual(4.5);
});

对于比较浮点数相等,使用 toBeCloseTo 而不是 toEqual,因为你不希望测试取决于一个小小的舍入误差。

1
2
3
4
5
test('两个浮点数字相加', () => {
const value = 0.1 + 0.2;
//expect(value).toBe(0.3); 这句会报错,因为浮点数有舍入误差
expect(value).toBeCloseTo(0.3); // 这句可以运行
});

字符串

您可以检查对具有toMatch正则表达式的字符串︰

1
2
3
4
5
6
7
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});

test('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/);
});

数组

你可以检查数组是否包含特定子项使用 toContain︰

1
2
3
4
5
6
7
8
9
10
11
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'beer',
];

test('购物清单(shopping list)里面有啤酒(beer)', () => {
expect(shoppingList).toContain('beer');
});

例外

如果你想要测试的特定函数抛出一个错误,在它调用时,使用 toThrow。

1
2
3
4
5
6
7
8
9
10
11
12
function compileAndroidCode() {
throw new ConfigError('you are using the wrong JDK');
}

test('compiling android goes as expected', () => {
expect(compileAndroidCode).toThrow();
expect(compileAndroidCode).toThrow(ConfigError);

// You can also use the exact error message or a regexp
expect(compileAndroidCode).toThrow('you are using the wrong JDK');
expect(compileAndroidCode).toThrow(/JDK/);
});

测试异步代码

回调

使用单个参数调用 done,而不是将测试放在一个空参数的函数。 Jest会等done回调函数执行结束后,结束测试。

1
2
3
4
5
6
7
8
test('the data is peanut butter', done => {
function callback(data) {
expect(data).toBe('peanut butter');
done();
}

fetchData(callback);
});

如果 done()永远不会调用,这个测试将失败,这也是你所希望发生的。

Promises

1
2
3
4
5
6
test('the data is peanut butter', () => {
expect.assertions(1);
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});

一定要返回 Promise - 如果你省略 return 语句,您的测试将在 fetchData 完成之前完成。如果你想要 Promise 被拒绝,使用 .catch 方法。 请确保添加 expect.assertions 来验证一定数量的断言被调用。 否则一个fulfilled态的 Promise 不会让测试失败︰

1
2
3
4
test('the fetch fails with an error', () => {
expect.assertions(1);
return fetchData().catch(e => expect(e).toMatch('error'));
});

.resolves / .rejects

您还可以使用 .resolves 匹配器在您期望的声明,Jest 会等待这一 Promise 来解决。如果 Promise 被拒绝,则测试将自动失败。

1
2
3
4
test('the data is peanut butter', () => {
expect.assertions(1);
return expect(fetchData()).resolves.toBe('peanut butter');
});

如果你想要 Promise 被拒绝,使用 .catch 方法。 它参照工程 .resolves 匹配器。 如果 Promise 被拒绝,则测试将自动失败。

1
2
3
4
test('the fetch fails with an error', () => {
expect.assertions(1);
return expect(fetchData()).rejects.toMatch('error');
});

Async/Await

1
2
3
4
5
6
7
8
9
test('the data is peanut butter', async () => {
expect.assertions(1);
await expect(fetchData()).resolves.toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
expect.assertions(1);
await expect(fetchData()).rejects.toMatch('error');
});
阅读全文 »

移动端下开发问题总结

发表于 2018-06-14 | 阅读次数

ios端微信浏览器会给input框加上自带的样式,例如圆角和内阴影。是因为-webkit-appearance这个属性的影响

解决:给input添加以下样式

1
2
3
4
5
input {
appearance: none;
-webkit-appearance: none; /* safari */
-moz-appearance: none;
}

ios微信端下z-index被transform属性影响

去掉transform属性

iOS的弹性滑动属性-webkit-overflow-scrolling: touch会导致z-index属性失效

去掉-webkit-overflow-scrolling???

webpack学习——loose模式

发表于 2018-05-29 | 阅读次数

简要介绍Babel6的loose mode。

简介

babel的松散模式将ES6代码转换为不遵循ES6语义的ES5代码。

两种模式

babel中的许多插件有两种模式:

  • 正常模式尽可能地遵循ECMAScript 6的语义。

  • 松散模式产生更简单的ES5代码。

通常,建议不要使用松散模式。优点和缺点是:

  • 优点:生成的代码可能更快,并且与旧引擎兼容。它也趋于更清洁,更“ES5式”。

  • 缺点:当你从ES6转换到ES6时,你可能会遇到问题。这很少是值得冒险的。

打开松散模式

es2015-loose预设是标准ES6预设的松散版本。它提供了一个概观如何打开某个插件的松散模式:

1
2
3
4
5
6
7
8
module.exports = {
plugins: [
···
[require("babel-plugin-transform-es2015-classes"), {loose: true}],
require("babel-plugin-transform-es2015-object-super"),
···
]
};

示例:松散模式和正常模式输出区别

让我们看看模式的区别如何影响到以下代码的输出:

1
2
3
4
5
6
7
8
9
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return `(${this.x}, ${this.y})`;
}
}

正常模式

正常模式下,类的属性通过Object.defineProperty:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"use strict";

var _createClass = (function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor); // (A)
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
})();

function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}

var Point = (function () {
function Point(x, y) {
_classCallCheck(this, Point);

this.x = x;
this.y = y;
}

_createClass(Point, [{
key: "toString",
value: function toString() {
return "(" + this.x + ", " + this.y + ")";
}
}]);

return Point;
})();

松散模式

松散模式下,通过正常添加方法方式,更像es5写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"use strict";

function _classCallCheck(instance, Constructor) { ··· }

var Point = (function () {
function Point(x, y) {
_classCallCheck(this, Point);

this.x = x;
this.y = y;
}

Point.prototype.toString = function toString() { // (A)
return "(" + this.x + ", " + this.y + ")";
};

return Point;
})();

前端知识学习概要

发表于 2018-05-02 | 阅读次数

了解web浏览器

  • 浏览器如何渲染页面

  • 浏览器的工作原理

  • What is a browser engine?

  • What forces layout / reflow

  • What Every Frontend Developer Should Know About Webpage Rendering

123…6
liaoyf

liaoyf

加油!

55 日志
23 标签
GitHub
© 2018 liaoyf
由 Hexo 强力驱动
主题 - NexT.Pisces