xwillmadeit

  • 首页
  • 归档
  • 标签

Webpack Loaders 进阶

发表于 2017-08-22

什么是 Loaders

Loaders 可以认为是 import 或 “load” 模块时的预处理工具。它可以对导入的不同类型的模块(css,ts,png)进行转化,成为 javascript 代码

核心原理

一个 loader 是一个 node module,导出一个方法,该方法接收一个参数(导入模块的内容,stream 或 string),返回一个经过转换的新字符串(或 stream),这就是 loader 的工作原理

1
2
3
4
// simplest loader
module.exports = function(source) {
return source
}

Loaders 主要特性

  • 支持级连,从右向左处理,每个 loader 都返回处理完成的代码给下一个 loader
1
use: ['style-loader', 'css-loader']
  • loaders 可以是异步也可以是同步

  • loaders 可以输出任意文件(emit files)
    如 file-loader

  • loaders 可以接受参数,主要有两种方式传入参数

1
2
3
4
5
6
7
8
9
10
11
// 1. query string
use: 'file-loader?name=images/[hash].[ext]'

// 2. options
use: {
loader: 'file-loader',
options: {
name: '[hash].[ext]',
outputPath: 'images/'
}
}

在 loaders 中接受参数:

1
2
3
4
5
6
const loaderUtils = require('loader-utils')

module.exports = function(source) {
const options = loaderUtils.getOptions(this)
return source
}

注意,上面的 options 值主要有几种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1. passing config using query string like
use: 'file-loader?name=images/[hash].[ext]'
// options equals to the query Object

// 2. passing config using options like
use: {
loader: 'file-loader',
options: {
name: images/[hash].[ext]
}
}
// options equals to the options object

// 3. passing config using both query and options
use: {
loader: 'file-loader?name=images/[hash].[ext]',
options: {
name: images/[hash].[ext]
}
}
// options equals to the options object

如何写一个 loader ?

我写了一个 demo,展示 loaders 是怎么工作的,包含如何调试 loaders

javascript 加减操作符中的类型转换

发表于 2017-07-30

为什么 1 + “1” 不等于 2,”5” - 2 等于 3?

1
2
3
4
5
// 为什么不等于 2
1 + "1" // "11"

// 为什么等于 3
"5" - 2 // 3

解答这个问题,我们必须了解 +(Addition Operator)和 -(Subtraction Operator) 的工作原理

加号操作符 The Addition operator

直接上文档

  • If Type(lprim) is String or Type(rprim) is String, then
    a. Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
  • Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim)

可以看到文档中写的很清楚,如果在加号的两边有一边是 string 类型,那么相加的时候,两边都会转化成 string,进行字符串拼接(string concatenation),如果加号两边都是 number 类型,则进行数字相加运算(numeric operands)

MDN 上关于 Addition Operator 操作符号的相关介绍

The addition operator produces the sum of numeric operands or string concatenation.

PS:如果加号两边有 boolean 值的话,该 boolean 值会被转化为 0 或 1,如

1
true + 5 // 6

减号操作符 The Subtraction Operator

文档

  • Let lnum be ToNumber(lval).
  • Let rnum be ToNumber(rval).
  • Return the result of applying the subtraction operation to lnum and rnum

可以看到减号操作符会把左右两边都转为 number 类型进行运算

1
2
"5" - 2 // 3
5 - "2" // 3

5 + +”5” 为什么等于 10

这里字符串前面的加号是 Unary + Operator

关于 Unary + Operator 的介绍:

The production UnaryExpression : + UnaryExpression is evaluated as follows:

  1. Let expr be the result of evaluating UnaryExpression.
  2. Return ToNumber(GetValue(expr)).

下面的表达式可拆分为两个步骤,首先对 + 右边的表达式进行求值,然后将返回的结果转化为数字

1
2
3
+"5" // 5

+function(){return "5"}() // 5

为什么IIFE语法需要小括号包裹

发表于 2017-07-29

IIFE 的语法

1
2
3
4
5
6
7
8
(function say() {
console.log('hello')
})()

// or
(function() {
console.log('hello')
})()

我们经常使用上面的语法来创建一个代码块,好处是能够将变量作用域保存在自执行函数中,不污染外部的变量,那么,为什么下面的语法会报错呢?

1
2
3
function say() {
console.log('hello')
}()

要弄清楚为什么报错,我们必须理解函数表达式和函数声明的区别

函数声明(Function Declaration)和 函数表达式 (Function Expression)

最显而易见的区别,是两者定义函数方式的区别:

函数声明

1
function say() {}

函数表达式

1
2
3
const say = function() {}
// or
const say = function say() {}

关于函数声明和函数表达式的更详细区别,不在本文赘述

为什么函数声明后面加一个小括号会报错?

答案很简单,调用一个使用函数声明定义的函数,必须使用函数名

1
2
3
4
5
6
7
function say(){}
say()

// not work
function say() {

}()

而用一对括号 Group Operator 包裹住函数,实际上是把函数声明转换成了函数表达式,而函数表达式可以有函数名也可以匿名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(function say() {

})()

(function() {

})()

// 可以拆成两步理解
// 1. 用括号包住函数,Group Operator 会进行一次求值 (evaluated),会返回一个变量
var say = (function say(){

})
// 2. 对该变量进行函数调用
say()

// 省去变量赋值相当于
(function say() {

})()

PS:() 操作符只能对表达式求值,所以被括号包裹住的函数是函数表达式定义的函数,这也是为什么这种自执行函数被叫做 IIFE(Immediately Invoked Function Expression),立即执行函数表达式

思考

那么,是不是只要想办法让解析器在遇到函数声明的时候能够进行一次求值转化为函数表达式,就能正常运行呢?

解决方法:

  • 逗号操作符 Comma Operator

  • 非操作符号 Logical Not Operator

1
2
3
4
5
6
7
0, function say(){}() 

!function say(){}()

+function say(){}()

// ...

只要能让该函数出现在的位置能被解析器当作表达式进行一次求值(evaluated)即可

参考:
Explain the encapsulated anonymous function syntax
JavaScript 匿名函数有哪几种执行方式?

情商2读书笔记

发表于 2017-07-25
  • 我们越是专心,就越能敏锐迅速的感受到他人的内心世界,不管周围环境多么复杂,他人的情感暗示多么细微。相反,我们越是紧张,就越难产生同理心。简而言之,不管什么形式的自我封闭都会扼杀同理心的产生,更不要说同情了。当我们以自我为中心时,我们遇到的问题就会越来越多,自我封闭就会越来越严重,我们的世界就会越来越小。而当我们关注他人时,我们的世界就会越来越丰富多彩,我们自己的问题就会显得渺小,而且我们的交往能力可以得到加强,从而引发帮助他人的善举。(p46)

  • 有意识的对别人多加关注可能是推动和谐人际关系的最佳方式。仔细倾听并专心致志,会激发和谐的要素——一致性和积极情感的产生。设身处地是社交上中最核心的能力之一。设身处地是美满婚姻的一个要素。(p80, 81 倾听和设身处地的重要性)

  • 在工作中,关怀他人并且承担起帮助他们的责任有助于建立良好的人际关系。总会有一些人非常乐意花费自己的时间和精力去帮助其他同事。他们不仅仅关心自己手头的工作,因为他们明白合作能够实现更高的集体目标。(p88)

  • 三心二意是现代生活的通病,在任何交流中都会造成伤害,特别是在对方情绪不佳的时候。(p96)

  • 日本文化(或者说整个东亚文化)中的价值观高度重视对别人需要主动提供帮助的行为。(p99)

  • 恋人们关系是否能够长久的最重要的指标是他们之间分享的积极情绪的多寡。消极的交流肯定不会预示着幸福的婚姻。他们对彼此越是不满,在争吵过程中双方的情绪就会越激动。在处理分歧的过程中,他们之间出现的消极情绪越强烈,今后的婚姻状况就越不稳定。快乐与不和谐的比例 5 : 1,说明夫妻有足够的健康情绪储备。(p204)

react-transition-group 使用方法

发表于 2017-06-29

初始化渲染 Transition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
render() {
return (
<CSSTransitionGroup
transitionName="example"
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnter={false}
transitionLeave={false}>

<h1>Fading at Initial Mount</h1>
</CSSTransitionGroup>

)
}

// css
.example-appear {
opacity: 0.01;
}

.example-appear.example-appear-active {
opacity: 1;
transition: opacity .5s ease-in;
}

必须设置 transitionName 属性,用于相应名称的 css 选择器
transitionAppear 默认值为 false,如需组件一加载就 transition,则设置为 true
在这里如果不需要 transitionEnter,transitionLeave,则需设置为 false(默认为 true)

动态增加、删除及显示隐藏 Transition

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
render() {
return (
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>

{ this.state.show &&
<div>toggled element</div>
}
</CSSTransitionGroup>

)
}

// css
.example-enter {
opacity: 0.01;
}

.example-enter.example-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}

.example-leave {
opacity: 1;
}

.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}

官方文档

node-glob使用

发表于 2017-06-28

Set up

1
npm i -D glob

Usage

1
2
3
glob(pattern, [options], (err, files) => {
// ...
})

Example

Pattern 1

1
src/**/*

改方法会递归匹配src文件夹下,任意子文件夹和文件 (不会匹配.开头的文件)

设置 dot: true 参数可将 . 当作普通字符

1
2
3
glob('src/**/*', { dot: true }, (err, files) => {
// ...
})

Pattern 2

1
src/**/*.*

改方法会递归匹配src文件夹下,任意子文件,不会匹配文件夹

Pattern 3

1
src/**/*.*(js|scss)

改方法会递归匹配src文件夹下,任意后缀为 js 或 scss 的文件

Pattern 4

1
src/**/*.!(js|scss)

改方法会递归匹配src文件夹下,任意后缀不为 js 或 scss 的文件

Pattern 5

1
.*

改方法会匹配当文件夹下,任意以 . 开头的文件 (.babelrc, .eslintrc)

关于 “.”

If a file or directory path portion has a . as the first character, then it will not match any glob pattern unless that pattern’s corresponding path part also has a . as its first character.
For example, the pattern a/./c would match the file at a/.b/c. However the pattern a//c would not, because * does not start with a dot character.
You can make glob treat dots as normal characters by setting dot:true in the options.

心静的力量

发表于 2017-06-18

Section 2

充满怨恨和嫉妒的人显然得不到内心平静,他们的人生会因为怨恨和嫉妒而走味。失败的人往往一看到成功的人就感到厌恶。成功人士对于别人的成功都会语带赞美,态度不是嫉妒,而是愿意向他人学习。反观失败的人,他们则会想尽办法对成功的人提出一些恶意批评。假如那个人做生意的方式找不到任何可议之处,就会从别的方面来挑毛病。怨恨显而易见,比这个更糟糕的还有一个可悲的要实:这种人不但享受不到金钱所能买到的东西,也得不到内心平静

不要为了成功而伤害任何人

如今是以提供服务为导向的大型企业时代,力公室人员常多如牛毛。工厂里的人通常是以他的产出来接受评断,但白领可以靠各种性格上的把戏
书面作业的把戏、把错误的责任推到别人身上等等的把戏来往上爬。踩在别人头上步步高升会使你所赚的钱沦为笑柄,这么做得不到内心平静,往往也得不到健康、快乐和家庭和谐。所剩下的只有用钱买得到的东西,而且不快乐的程度会比乞丐还强烈。

永远多一份付出

愿意做的比必须做的多是一帖兴奋剂,这本身就是赚大钱的人,优秀的领导者以及快乐又有热忱的人所具备的特色,他们天天都在为生活创造价值。

看到自己往上爬到了一阶梯子,再往上方一阶,以及前方有所回报的许多阶,这个画面就会深植在你内心,并激励你往上爬。万一遇到付出额外努力却得不到回报的情形,充满正面能量的内心就会找来勇气与谋略。你会离开不适合自己的工作,把它送进过往,然后去找另一份由想象中的画面转变为现实的工作。从哪里开始绝对远远比不上要往哪里去来得重要,在内心里好好构思并开始前进才是首要之务。

尤其在工作上,怨恨和愤概的情绪会损害内心构思与实践的能力。多一分付出对于摆脱内心存在的障碍具有振起的作用。对工作的投入要超越所领的薪酬,随时让白己有资格晋升到上一阶或上几阶。成功的人不会是心怀怨恨或者不全力以赴的人,而会是一言一行都在为更远大目标铺路的人。

好用的前端库/包整理

发表于 2017-06-15

Surge

Surge 是一个静态资源部署工具,支持一行命令部署静态资源到 project.surge.sh,只需要指定需部署的文件夹以及二级域名

1
2
3
4
5
6
7
8
9
10
// installation
npm install -g surge

// package.json
"scripts": {
"deploy": "surge /Users/xwill/learnCode/freeCode/vanilla xwillmadeit.surge.sh"
}

// deploy
npm run deploy

now

now 是 zeit 出品的命令行一键部署工具,支持部署 node 项目以及静态网站项目

1
2
// installation
npm i -g now

静态网站部署

在需要部署的目录(如 dist,有 index.html),直接执行 now 即可,每次部署会生成一个随机 url,类似于 https://dist-ktxztztigq.now.sh

node 项目部署(以 zeit 的 micro 为例)

参考官方

删除当前正在部署的进程

1
now rm app-name

修改 url:

1
now alias https://dist-etjnigdrkz.now.sh hello

Tricks - 部署一个带有 Browser History 路由的 SPA

以 create-react-app 为例,执行构建后,会生成一个 build 文件夹,在 build 文件夹中执行

1
npm init -y

生成 package.json,修改相应的 package.json 信息,然后添加 scripts

1
2
3
"scripts": {
"start": "serve --single"
}

然后安装 serve

npm i -S serve

最后执行 now 即可

如何发布自己的npm包

发表于 2017-06-07

目标

在 npm 上发布一个适合团队代码风格的 eslint 配置包,项目名称为 eslint-config-vpgame

开发 eslint-config-vpgame

如何编写这个包并不是重点,代码直接戳这里

使用 npm link 调试工具包

假定我们的包已经开发完毕,我们需要在其他项目中安装这个包进行测试。众所周知,如果在项目中需要引入 eslint-config-vpgame 包的话,我们需要执行

1
npm install eslint-config-vpgame --save-dev

但是在开发这个包的时候,我们不可能每次先发布到 npm 仓库,然后再在其他项目中使用 npm install 的形式来进行测试,我们希望在其他工程中能实时测试当前正在开发的 npm 包的效果,这里我们需要用到 npm link 命令

在当前开发的 eslint-config-vpgame 目录下执行

1
npm link

npm 会把该包关联到本机的 npm 全局安装目录下,即模拟了安装的效果

在另一个项目中使用:
创建新项目 some-project:

1
2
npm init -y
npm link eslint-config-vpgame

此时该项目会增加一个 node_modules 文件夹,即实现了 npm install 效果
当修改 eslint-config-vpgame 包的时候,该项目 node_modules 文件夹下的 eslint-config-vpgame 包也会自动更新

wow…大大的节省了测试时间

发布到 npm

到这步就很简单了,在 eslint-config-vpgame 项目根目录下执行

1
npm publish

如果没有帐号的话,按照提示设置一下就好了… 大功告成

PS:注意,最好先建好 git repo,然后 npm init -y 初始化项目,这样 package.json 中会关联 repo 地址,npm 项目主页面就可以展示 git repo 地址

Jenkins自动化集成

发表于 2017-06-06

什么是 Jenkins

https://jenkins.io/

安装和启动

将下载完的 jenkins.war 上传至服务器

1
scp /Users/xwill/Downloads/jenkins.war root@115.28.136.223:/usr/local/jenkins

启动 Jenkins

1
java -jar jenkins.war

这里默认服务器上已经装了 JDK,服务启动之后,在 8080 端口访问,进行一些列配置后,jenkins 搭建完毕

集成 github

首先配置 Github 相关内容
Github 个人设置中生成一个 Personal Access Token

在 Project Setting 中添加 Jenkins Hook URL

配置 Jenkins 的 Github 配置

找到 Github 区域,API URL 默认不变,点击 Add 创建一个新的证书

Kind 选择 Secret text,Secret 填写 Personal Access Token

系统配置完后,我们可以新建项目了
在 jenkins 后台新建 freestyle project

在 general 面板勾选 Github project,填入 Project url

在 Source Code Management 面板勾选 Git,填入 Repository URL,其他保持默认即可

在 Build Triggers 面板勾选 GitHub hook trigger for GITScm polling

在 Build Panel 面板选择 Execute shell,填入 npm run build(举个栗子)

完成以上配置以后,点击 Save,项目就创建完成了。此时如果提交修改并 push 最新代码到 github,Jenkins 会帮你执行:

1
2
git pull
npm run build

构建相关信息可在项目页面找到

PS:服务器上默认的代码被放在下面目录

1
/root/.jenkins/workspace

集成 Gitlab

准备工作:
把服务器的 SSH Key 填到 gitlab 中,使服务器(Jenkins)有权限拉取 gitlab 的代码
在 Jenkins 中搜索 gitlab 相关插件,全部安装即可

集成:
首先配置系统的 gitlab 相关内容(Configure System)

这里的证书选择 gitlab 的 Token,如果没有的话添加一个,步骤参考集成 github 中新增 token 的操作。token 可在 gitlab 个人设置的 Account 中找到

后续创建项目的步骤与 github 类似,需要注意两点:
repo 地址使用 ssh 格式

gitlab 相关项目的 Web Hooks 地址设置为:

其他与 github 一样

12…5
xwillmadeit

xwillmadeit

44 日志
48 标签
© 2017 xwillmadeit
由 Hexo 强力驱动
主题 - NexT.Muse