小被子

小被子 查看完整档案

深圳编辑  |  填写毕业院校shopee  |  前端 编辑 juejin.im/user/5c7be58451882546c67decaf/posts 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

小被子 收藏了问题 · 11月3日

关于 Set-Cookie 的 domain 的问题

一般让 cookie 在所有子域都有效的话会写成这样

Domain=.segmentfault.com

我想问第一个点是必需的吗,写成下面这样有没有问题

Domain=segmentfault.com

小被子 提出了问题 · 6月10日

如何使用 react-native 实现多行对齐的样式?

image.png
如图:需要使用 RN 实现这样的一种样式,第一行的 title 和 第三行的百分比最多会有两行,中间的值最多一行,当高度被撑开时,需要每一行保持对齐,请问怎么使用 RN 怎么实现这种效果呢?

关注 4 回答 2

小被子 赞了文章 · 5月25日

打破砂锅问到底:详解Webpack中的sourcemap

关于webpack中sourcemap的文章很多,但感觉大部分是翻译官方文档的说明, 缺乏直观的用例,写这篇博客的目的是帮自己厘清这个概念, 也顺便将我自己收集的这方面的干货放在这。本文将尝试先讲清楚webpack中的sourcemap配置项的概念。

Webpack中sourcemap的配置

sourcemap是为了解决开发代码与实际运行代码不一致时帮助我们debug到原始开发代码的技术。尤其是如今前端开发中大部分的代码都经过编译,打包等工程化转换。比如开发环境下用scss写样式, 想在浏览器中在线编辑css那样编辑scss就不是那么容易了。从我自己看过的资料中, sourcemap的概念最早出现在12年, jquery1.9是较早支持sourcemap的库。这篇博客比较有代表性:Introduction to JavaScript Source Maps,阮一峰的文章JavaScript Source Map 详解也大量参考该博客。关于sourcemap的原理及作用,基本在这两篇文章中讲清楚了。回到webpack中的sourcemap,就我这几天的琢磨, 这方面资料相对比较零散,但凡搜索Webpack中sourcemap的配置, 总是能得到千篇一律的如下信息:
Sourcemap type Quality Notes

eval: 生成代码 每个模块都被eval执行,并且存在@sourceURL

cheap-eval-source-map: 转换代码(行内) 每个模块被eval执行,并且sourcemap作为eval的一个dataurl

cheap-module-eval-source-map: 原始代码(只有行内) 同样道理,但是更高的质量和更低的性能

eval-source-map: 原始代码 同样道理,但是最高的质量和最低的性能

cheap-source-map: 转换代码(行内) 生成的sourcemap没有列映射,从loaders生成的sourcemap没有被使用

cheap-module-source-map: 原始代码(只有行内) 与上面一样除了每行特点的从loader中进行映射

source-map: 原始代码 最好的sourcemap质量有完整的结果,但是会很慢

webpack中devtool的配置的官方文档在这 :webpack-devtool

疑问

反正我看完这些说明是云里雾里, 就我自己而言, 有3个疑问:

  1. eval和sourcemap有什么关系,eval模式是sourcemap吗?
  2. 包含cheap关键字的配置中只有行内是什么意思?
  3. 这几种不同的配置有什么区别?

解答

看似配置项很多, 其实只是五个关键字evalsource-mapcheapmoduleinline的任意组合。这五个关键字每一项都代表一个特性, 这四种特性可以任意组合。它们分别代表以下五种特性(单独看特性说明有点不明所以,别急,往下看):

  • eval: 使用eval包裹模块代码
  • source-map: 产生.map文件
  • cheap: 不包含列信息(关于列信息的解释下面会有详细介绍)也不包含loader的sourcemap
  • module: 包含loader的sourcemap(比如jsx to js ,babel的sourcemap)
  • inline: 将.map作为DataURI嵌入,不单独生成.map文件(这个配置项比较少见)

了解了以上各种不同特性, 再来逐一解答以上问题。

eval和sourcemap有什么关系,eval模式是sourcemap吗?

evalsource-map都是webpack中devtool的配置选项, eval模式是使用eval将webpack中每个模块包裹,然后在模块末尾添加模块来源//# souceURL, 依靠souceURL找到原始代码的位置。包含eval关键字的配置项并不单独产生.map文件(eval模式有点特殊, 它和其他模式不一样的地方是它依靠sourceURL来定位原始代码, 而其他所有选项都使用.map文件的方式来定位)。包含source-map关键字的配置项都会产生一个.map文件,该文件保存有原始代码与运行代码的映射关系, 浏览器可以通过它找到原始代码的位置。(注:包含inline关键字的配置项也会产生.map文件,但是这个map文件是经过base64编码作为DataURI嵌入),举个栗子:eval-source-mapevalsource-map的组合,可知使用eavl语句包括模块,也产生了.map文件。webpack将.map文件作为DataURI替换eval模式中末尾的//# souceURL。按照我自己的理解, eval.map文件都是sourcemap实现的不同方式,虽然大部分sourcemap的实现是通过产生.map文件, 但并不表示只能通过.map文件实现。下面是eval模式后产生的模块代码:
图片描述

包含cheap关键字的配置中只有行内是什么意思?

这里的列信息指的是代码的不包含原始代码的列信息。 官方文档对于包含cheap的解释是这样的:

> cheap-source-map - A SourceMap without **column-mappings**. SourceMaps
> from loaders are not used.

  

这句话翻译过来就是“在cheap-source-map模式下sourcemap不包含列信息,也不包含loaders的sourcemap”这里的“column-mappings”就是代码列数的意思,是否包含loaders的sourcemap有什么区别将在之后提到。debug的时候大部分人都只在意代码的行数, 很少关注列数, 列数就是该行代码从第一个字符开始到定位字符的位置(包括空白字符)包含cheap关键字的模式不包含列信息,体现在webpack中就是:如果包含cheap关键字,则产生的.map文件不包含列信息。也就是说当你在浏览器中点击该代码的位置时, 光标只定位到行数,不定位到具体字符位置。而不包含cheap关键字时, 点击控制台log将会定位到字符位置。

包含列信息后点击原始代码的定位,注意光标位置:
图片描述

不包含列信息的光标位置:
图片描述

这篇博客:Go to a line number at a specific column直观地展示了列数的概念。如果深入到webpack中的细节中体会该配置项,可以看这篇博客:SurviveJS:Source Maps ,该文章对比了webpack中所有配置项中.map文件的代码,这里截取eval-source-mapcheap-source-map的模式产生的.map文件代码中的mappings字段对比:

devtool: 'eval-source-map'

"mappings": "AAAAA,QAAQC,GAAR,CAAY,aAAZ",

devtool: 'cheap-source-map'


```
"mappings": "AAAA",
```

注:这里使用了VLQ编码,(关于VLQ编码还可参考这里:前端构建:Source Maps详解) 在VLQ编码中,逗号,表示字符列分割,分号;表示行分割。包含cheap关键字的配置项不包含列信息,也就没有逗号。关于VLQ编码, 本文最初的阮一峰的文章中有所解释。而不包含loader的sourcemap指的是不包含loader的sourcemap,不包含它时候如果你使用了诸如babel等代码编译工具时, 定位到的原始代码将是经过编译后的代码位置,而非原始代码。

比如当我用babel编译JS的时候,如果包含不包含loaders的sourcemap,此时debug到的将是编译后的代码, 而非原始代码,如图(这是使用cheap-source-map模式未包含loaders的sourcemap情况下的截图, debug的位置与之前的对比截图是同一个地方):
图片描述

这几种不同的配置有什么区别?

通过以上两个问题的解释, webpack中的sourcemap各个配置项异同应该有了一定认识,乍看之下各个配置项很难记忆, 但其实从每个关键字所代表的特性入手, 就能体会到他们的异同。他们在webpack中的主要区别一个体现在重构的性能上, 总的来说eval性能最好,source-map性能最低,但就我自身的实践来看大多用的是最完整的source-map,该模式对于不管是js还是css,scss等都能很好的覆盖, 相反其他模式都不完整, 在开发环境下重构性能似乎比不上功能的完善。
另外需要补充的是module关键字, 当加上module关键字webpack将会添加loader的sourcemap。

这篇博客:Webpack devtool source map 对于各个sourcemap配置项都作了对比和梳理, 有趣的是,作者在该文中也指出对于很多官方文档的不解,比如对于所谓的without column-mappings作者就不知道在讲什么:

A SourceMap without column-mappings. SourceMaps from loaders are not
used.No idea what that means
查看原文

赞 101 收藏 81 评论 4

小被子 收藏了问题 · 4月20日

webpack使用DefinePlugin设定环境变量的问题

最近在看webpack4的官方文档时,被一个东西弄混了,就是使用DefinePlugin设定环境变量的问题,见代码:

import webpack from 'webpack';

// 如果预先定义过环境变量,就将其赋值给`ASSET_PATH`变量,否则赋值为根目录
const ASSET_PATH = process.env.ASSET_PATH || '/';

export default {
  output: {
    publicPath: ASSET_PATH
  },

  plugins: [
    // 该插件帮助我们安心地使用环境变量
    new webpack.DefinePlugin({
      'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH)
    })
  ]
};

这是官网上的代码这是链接

我想问一下,上面是取process.env.ASSET_PATH赋给ASSET_PATH ,下面有使用DefinePlugin设定process.env.ASSET_PATH的值为ASSET_PATH ,这是什么意思啊?
有没有大神,能解释的通俗易懂一点,谢谢!

小被子 提出了问题 · 2月24日

codemirror 在多个 tab A下的 sql 提示切换到 tab B 还是会存在

在 react 项目中使用 codemirror 来创建一个 sql 编辑器

样式如下:左侧每个 tab 对应一个 sql 编辑器
image.png

代码如下:

import { Controlled  as  CodeMirror } from  'react-codemirror2'
import  'codemirror/mode/sql/sql'
import  'codemirror/addon/hint/show-hint'
import  'codemirror/addon/hint/sql-hint'

render() {
    const { id, sql, queryName, isSaveMadalShow, queryId, isRunning } =  this.state
    const { queryTab, dataSourceId, dbName } =  this.props
    const { tableList = [], dataBaseList, tables } =  queryTab
    const  dataBaseNames = dataBaseList.map(item => ({[`FROM ${item.label}.`]: []}))
    const  tableNames =  tables.map(item => ({[`FROM ${item.label}`]: []}))
    
  <CodeMirror
    ref={(cm) => {this.codeMirror = cm}}
    value={sql}
    options={{
    mode: { name:  'text/x-mysql' },
    theme:  'monokai',
    indentWithTabs:  true,
    smartIndent:  false, // 自动缩进
    readOnly:  false,
    lineNumbers:  true, // 显示行号
    lineWrapping:  'wrap', // 长行时文字是 wrap(换行)
    matchBrackets:  true,  // 括号匹配
    extraKeys: {
        Tab:  'autocomplete', // 按 Tab 出现联想
    },
    hint:  CodeMirrorHintSQL,
    hintOptions: {
        completeSingle:  false,
        tables:  Object.assign({}, ...tableNames, ...dataBaseNames)
      }
    }}
    onBeforeChange={(editor, data, value) => {
        this.setState({
            sql:  value,
        })
    }}
    onChange={throttle(this.autoSaveQuery, 2000)}
    onCursorActivity={(editor) => {
        // 调用显示提示
        // console.log('cursor activity')
        editor.showHint()
    }}
  />
}

切换 tab 时, tabA 的 sql 提示切换到 tabB 时还是会存在,如图就是从 query 4 切换到 irene test 2 的过程,可以看到存在 query 4 的 sql 提示(SELECT),请问这是什么原因?该如何改呢?
image.png
image.png

关注 1 回答 0

小被子 赞了文章 · 1月2日

前端基础进阶目录

前端基础进阶(一):内存空间详细图解

前端基础进阶(二):执行上下文详细图解

前端基础进阶(三):变量对象详解

前端基础进阶(四):详细图解作用域链与闭包

前端基础进阶(五):全方位解读this

前端基础进阶(六):在chrome开发者工具中观察函数调用栈、作用域链与闭包

前端基础进阶(七):函数与函数式编程

前端基础进阶(八):深入详解函数的柯里化

前端基础进阶(九):详解面向对象、构造函数、原型与原型链

前端基础进阶(十):面向对象实战之封装拖拽对象

前端基础进阶(十一):详细图解jQuery对象,以及如何扩展jQuery插件

前端基础进阶(十二):深入核心,详解事件循环机制

前端基础进阶(十三):透彻掌握Promise的使用,读这篇就够了

前端基础进阶(十四):es6常用基础合集

前端基础进阶(十五):详解 ES6 Modules

这系列文章是我一年前在简书写的文章,因为一些特殊原因,不打算在简书写文章了,所以把文章迁移到了segmentfault里来。不过其实简书文章评论里有很多大家的问题以及解答,对于进一步理解文中知识帮助很大的,算是有点可惜吧。不过也希望能够对正在学习前端的你有一些小帮助。

如果在阅读中发现了一些错误,请在评论里告诉我,我会及时更改。

在segmentfault写文章也写了好几十篇了,从来没被赞赏过,不知道这一波文章能不能混点赞赏呢 -> -> -> ->

查看原文

赞 438 收藏 1356 评论 27

小被子 赞了回答 · 2019-08-29

设置html body的高度为百分比时,margin-bottom在safari里失效?

用padding-bottom
app {

margin-top: 50px;
padding-bottom: 50px;

}
完美解决问题!

关注 5 回答 4

小被子 回答了问题 · 2019-07-18

解决tsconfig.json 中 exclude node_modules,但 tsc 还是执行到里面去了?

关注 4 回答 4

小被子 提出了问题 · 2019-07-17

解决tsconfig.json 中 exclude node_modules,但 tsc 还是执行到里面去了?

我照着这篇文章搭建一个 TypeScript NPM 包,当第一次执行 npm run build时,能正常运行,当下载完 jest 之后再次运行 npm run build 报如下错:

tsc node_modules/@types/babel__template/index.d.ts:16:28 — error TS2583: Cannot find name ‘Set’. Do you need to change your target library? Try changing the lib compiler option to es2015 or later.

16 placeholderWhitelist?: Set;

Found 1 error.

我的 node, npm, tsc 的版本分别是: node -v // v8.12.0, npm -v // v6.4.1, tsc -v // v3.4.5

项目代码:https://github.com/irenetang1...

为什么我在 tsconfig.json 中已经 exclude node_modules了,tsc 还是执行到 node_modules 里面去了?

关注 4 回答 4

小被子 发布了文章 · 2019-06-25

cookie

需求场景

一个Vue单页应用,A、B、C 三个页面都引用了一个公用的时间选择器。用户在各自页面选择完时间后,A,B,C页面互相切换时保存选择的时间,在关闭浏览器tab后,清除选择的时间,恢复初识值。一开始的想法是使用会话 cookie(不手动设置过期时间),但是会话 cookie 在关闭浏览器 tab 的时候不会被清除。所以决定研究下会话 cookie 何时清除。

cookie

  • 背景

HTTP 是一种无状态的协议,它不对请求和响应之间的通信状态进行保存,即无法根据之前的状态进行本次请求的处理。假如要求登录验证的 web 页面本身无法进行状态的管理,那么每次跳转新页面就要再次登录,或者要在请求报文中附加参数来管理登录状态。无状态协议有它的优点,由于不必保存状态,可以减少服务器的 CPU 及内存资源。为了保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了 cookie。

  • 原理

cookie 技术通过在请求和响应报文中写入 cookie 信息来控制客户端的状态。cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 cookie 值后发送出去。
服务端发现客户端发送过来的 cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。

  • 客户端设置

    // 属性之间由一个分号和一个空格隔开
    document.cookie = 'name=value; expires=date; path=path'

    // 设置多个cookie
    document.cookie = 'name=irene; domain=www.baidu.com';
    document.cookie = 'age=18; path=/welcome';

document.cookie 一次只能设置一条 cookie,如果需要设置多条,需要多次设置。客户端可以设置的属性有:expires、max-age、domain、path、secure(https协议下才能设置成功),不能设置 HttpOnly。

服务器端设置

  Set-Cookie: name=value[; expires=date][; domain=domain][; path=path][; secure]

  // 设置多个cookie
  Set-Cookie: name=irene; domain=www.baidu.com;
  Set-Cookie: age=18; path=/welcome;

一个 Set-Cookie 只能设置一条 cookie,如果需要设置多条,需要多次使用 Set-Cookie。cookie 除了设置名称和值之外,还可以设置其他的属性。服务端可以设置的属性有:expires、max-age、domain、path、secure、HttpOnly 等。

属性

expires 和 max-age

设置 cookie 的失效时间。expires 的值是一个时间点(cookie 失效时刻 = expires),max-age 的值是秒数(cookie 失效时刻 = 创建时刻 + max-age)。expires 是 http/1.0 协议中的选项,在新的 http/1.1 协议中 expires 已经由 max-age 选项代替。如果两者同时存在,max-age 的优先级高于 expires。max-age 有两种可能值:小于等于0:有效期为能表示的最早时间;大于0:有效期为当前时间 + max-age。

// expires
document.cookie='name=irene; expires=Wed, 13 Jun 2019 10:28:27 GMT'
// max-age > 0
document.cookie='name=irene; max-age=3600'
// max-age <= 0
document.cookie='name=irene; max-age=0'

注意:一旦 cookie 从服务器端发送至客户端,服务器端就不存在可以显式删除 cookie 的方法。但可通过覆盖 cookie,实现对客户端 cookie 的删除操作。

domain & path

Domain 设置域名,默认是当前域名。path 设置路径,默认是当前目录。domain 和 path 一起限制了哪些请求可以带上该 cookie。比如上面第二个的 cookie,若请求的 URL 的域名是 juejin.com 或 xxx.juejin.com,并且 URL 的路径是 / 或 子路径 '/home',则浏览器会将此 cookie 添加到该请求的 cookie 头部中。

// 在 https://juejin.im/welcome/frontend 设置如下 cookie,则浏览器 Cookie 面板显示的 domain=juejin.im,path=/welcome
document.cookie = 'name=irene'
// 在 https://juejin.im/welcome/frontend 设置如下 cookie,则浏览器 Cookie 面板显示的 domain=.juejin.im(有前缀.),
document.cookie = 'name=irene; domain=juejin.im; path=/welcome/frontend'
// 关于 domain 有无前缀点可参考 http://www.it1352.com/548425.html
HttpOnly

当设置了 HttpOnly,浏览器就不会将该 cookie 添加到非 HTTP 请求的头部。
设置 cookie 是否能通过 js 去访问(读取、修改、删除等)。默认情况下,cookie 不会带 HttpOnly 选项,所以客户端是可以通过 js 代码去访问这个 cookie 的。当 cookie 带 HttpOnly 选项时,客户端则无法通过 js 代码去访问这个cookie。主要目的是为防止跨站脚本攻击对 cookie 的信息窃取。HttpOnly 只能从服务端设置,不能通过客户端设置。

Secure

设置仅在 HTTPS 安全连接时,才可以发送 cookie。

浏览器对于是否携带 cookie 项的策略

domain-matching

一个字符串(str)匹配(domain-matches)一个给定的域名字符串(domain str)至少需要满足以下条件中的一个:

  1. str 和 domain str 完全相同(转成小写后比较)。
  2. 或者同时满足以下条件:
    2.1 domain str 是 str 的后缀。
    2.2 str 中最后一个不包含在 domain str 中的字符是点(.)。

    domain str = google.com;  str = map.googole.com  =>  符合
    domain str = google.com;  str = map.mgoogle.com  =>  最后一个不包含在 domain str 中的字符是 m,不符合 

    2.3 str 必须是一个域名,而不是 IP 地址。

path-matching

一个请求路径(request-path)匹配(path-matches)一个给定的 cookie-path 至少需要满足以下条件中的一个:

  1. request-path 和 cookie-path 完全一样。
  2. cookie-path 是 request-path 的前缀,并且 cookie-path 的最后一个字符是 / 。
  3. cookie-path 是 request-path 的前缀,并且 request-path 中第一个不包含在 cookie-path 中的字符是 / 。

注意:domain-matching & path-matching 只是浏览器决定是否携带 cookie 诸多参考项中的其中两个,浏览器还会参考诸如是否过期等项。

实践

问题:

cookie 不设置失效时间的话,默认是会话结束失效,这个会话结束是指浏览器的所有窗口都关闭,还是说这个网站的页面全部关闭就可以了?

具体场景:

Chrome浏览器开了两个窗口A B,A打开了网站1的两个标签页(tab1 & tab2)和网站2的两个标签页(tab3 & tab4),B打开了网站1的两个标签页(tab1 & tab2)和网站2的两个标签页(tab3 & tab4),如果想网站1的cookie失效的话,是不是把窗口A B关于网站1的tab页关掉就行 还是 需要把浏览器的所有窗口都关闭?

实验对象:

https://segmentfault.com。它的 PHPSESSION 是会话结束失效,所以用来测试。

工具:

通过chrome://settings/cookies/detail?site=segmentfault.com查看该网站下的所有cookie。

结论:

浏览器的所有窗口都关闭,网站1的cookie(会话cookie)才失效。windows 在浏览器窗口都关闭的情况下,会退出程序,所以 cookie 会失效;mac 在浏览器窗口都关闭的情况下,不会退出程序,所以 cookie 不会失效,需要退出程序 cookie 才失效。

规范

如果一个 cookie 同时设置了 Max-Age 和 Expires 属性,Max-Age 的优先级更高。如果两个都没有设置,UA 会保存该 cookie 直到当前 会话结束。

查看原文

赞 3 收藏 1 评论 0

认证与成就

  • 获得 122 次点赞
  • 获得 152 枚徽章 获得 9 枚金徽章, 获得 48 枚银徽章, 获得 95 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-10-27
个人主页被 1.9k 人浏览