Leo‘s SSR


  • 首页

  • 标签2

  • 归档9

vscode配置

发表于 2018-06-09

个人配置项目

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
// 保存时设置文件的格式。格式化程序必须可用,不能自动保存文件,并且不能关闭编辑器。
"editor.formatOnSave": false,
// 默认打开缩进线插件
"guides.overrideDefault": true,
// tab展开html标签
"emmet.triggerExpansionOnTab":true
,
// 默认缩进
"editor.tabSize": 2,
// 禁止根据文件类型自动设置tabsize的选项
"editor.detectIndentation": false,
"editor.wordWrap": "on",
"files.autoSave": "off",
"eslint.validate": [
// "javascript",
// "javascriptreact",
// "html",
// { "language": "vue", "autoFix": true }
// { "language": "html", "autoFix": false }
],
"eslint.options": {
"plugins": [
"html"
]
},
// 自动格式化代码
"eslint.autoFixOnSave": false,
// 控制字体系列。
"editor.fontFamily": "Source Code Pro, Menlo, Monaco, 'Courier New', monospace",
"workbench.colorTheme": "Atom One Dark",
"editor.renderIndentGuides": false,
"sync.gist": "48b0f2c1f62b9f48854bb24e8a4a21fb",
"sync.lastUpload": "2017-11-14T11:04:45.359Z",
"sync.autoDownload": false,
"sync.autoUpload": false,
"sync.lastDownload": "",
"sync.forceDownload": false,
// "sync.anonymousGist": false,
"sync.host": "",
"sync.pathPrefix": "",
"sync.quietSync": false,
"sync.askGistName": false,
"explorer.confirmDelete": false,
// 启动markdown的自动预览功能
"markdown.extension.preview.autoShowPreviewToSide": true,
// 禁用js默认自动验证
"javascript.validate.enable": false,
// 启用基于standard的自动修复功能
"standard.autoFixOnSave": true,
// 自定义作者名称
"fileheader.Author": "lvkunpeng",
"fileheader.LastModifiedBy": "lvkunpeng",
// SVN设置:忽略文件夹
"svn.multipleFolders.ignore": [
"**/.git",
"**/.hg",
"**/vendor",
"**/node_modules",
"**/turbo"
],
"vsicons.dontShowNewVersionMessage": true,
"workbench.panel.location": "bottom",
"gitlens.advanced.messages": {
"suppressShowKeyBindingsNotice": true
}
}

插件列表

  • Atom One Dark
  • Auto Close Tag
  • Bracket Pair Colorizer 括号颜色 对齐线颜色
  • Code Outline
  • Code Runner
  • Color Highlight
  • Debugger for Chrome
  • EditorConfig for VS Code
  • ESLint
  • Git History
  • Guides(对齐线)
  • HTML CSS Support
  • HTML Snippets(闭合标签)
  • Markdown All in One
  • Node modules resolve
  • open in browser
  • Output Colorizer
  • Path Intellisense
  • Prettify JSON(JSON规范化)
  • Project Manager
  • Settings Sync
  • SVG Viewer
  • Twig
  • Vetur
  • vscode-icons
  • VueHelper

rss推送技术——打造自己的今日头条

发表于 2018-05-10

前言

最近由于个人事务繁重(懒、需求急),忙着在搞家里人的落户问题,以后可以开个帖子专门讲下。无暇顾及更博的问题,虽然也没人看。在此反思1分钟!罚酒三杯,下不为例!

RSS是啥

为了保证解释准确特意查了维基,RSS最早应用于1999年。也是网景公司提出并开发的。RSS的英文原意是 Really Simple Syndication 即“简易信息聚合”。是一种XML的标准。RSS的目的就是把新闻标题、摘要(Feed)、内容按照用户的要求,“送”到用户的桌面。其实就是对一些你想要关注的博客,公众号,新闻等等的更新摘要提取出来推送给你。

RSS的好处

  • 来源多样的个性化“聚合”特性。
  • 信息发布的时效、低成本特性。
  • 无“垃圾”信息、便利的本地内容管理特性。

当下来看,使用RSS技术使你再也不会被一些充满广告的的新闻平台推送不感兴趣的信息。也减少了被恶意收集数据的可能

RSS的缺点

  • 有一定的学习成本(相比只用下app的新闻平台)
  • 部分新闻源不支持RSS技术
  • 不能参与对内容的讨论,减少了互动性

其实对于部分新闻平台来说,不参与讨论,看不到评论感觉可能也算优点了。。。

使用RSS

使用RSS其实并不难,你只需要选择一个适合自己的RSS新闻阅读器,跟去订阅自己喜欢的新闻源就可以了,当然你也可以通过开源方案搭建自己的RSS阅读服务。

阅读器推荐

  • ios :Reeder
  • mac :Reeder
  • windows:都很老了建议使用web版
  • 全平台:Feedly Inoreader NewsBlur

此处不再做各家阅读器的对比,请参考少数派的文章

ps:类似少数派、爱范儿这种媒体资讯的网站都是支持RSS订阅的

订阅方法

最简单的方法,先找到网站上的RSS的图标如下
0000.png

有就代表本网站支持RSS订阅,点击就会弹出订阅的链接

下面按照 Feedly 举例:

  • 搜索得到的RSS地址

0001.png

  • 关注到你想放入的分类

00002.png

到此你就成功订阅了一个自己喜欢的RSS资源站点

RSS订阅源推荐

下面给大家推荐一些我关注的新闻源,部分需要科学上网

  • 36氪
  • 知乎日报
  • 果壳网
  • 知乎每日精选
  • 联合早报-国内
  • 联合早报-国际
  • 路透中文
  • 爱范儿
  • 编程随想

也可以通过阅读器上的选项一键导出你的收藏源,方便分享给其他人,或者做源的同步

结尾

至此,你就拥有了属于自己高度定制的新闻集合,帮助你更高效的获取信息。当然一些不支持的源可以通过爬虫的方式自建实现爬取推送(爬虫使用的是scrapy,组装rss信息源使用的是PyRSS2Gen)。或者利用别人烧录好的RSS生成器来生成订阅源

eg:

1
2
https://github.com/hutushen222/JianshuRSS   
只需要知道作者的地址,就可以一键生成简书的RSS

可以将你知道的,或者经常浏览的网站制作成RSS,以后你只需要一个app就够了。。欢迎大家分享你觉得不错的RSS源。RSS是一种美德!

pwa 入门实践-manifest清单文件

发表于 2018-04-18

manifest(清单文件)

定义:

manifest(清单文件)其实就是一个JSON文件,提供应用相关的信息
eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name": "Progressive Times web app",
"short_name": "Progressive Times",
"start_url": "/index.html",
"display": "standalone",
"theme_color": "#FFDF00",
"background_color": "#FFDF00",
"icons": [{
"src": "homescreen.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "homescreen-144.png",
"sizes": "144x144",
"type": "image/png"
}
]
}

  • name 用作当用户被提示安装应用时出现的文本。同时也是启动页面显示名字
  • short_name 用作当应用安装后出现在用户主屏幕上的文本
  • start_url 决定了当用户从设备的主屏幕开启 Web 应用时所出现的第一个页面。根据构建的 Web 应用类型,你可能需要预设如何首次加载。display 字段表示开发者希望他们的 Web 应用如何向用户展示。
  • theme_color 字段,可以对浏览器的地址栏进行着色,以符合网站的主色调。
  • icons 字段决定了当 Web 应用被添加到设备主屏幕时所显示的图标。
  • background_color 启动页面的颜色
  • display 设置启动页面的显示模式
    • Fullscreen - 打开 Web 应用并占用整个可用的显示区域。
    • Standalone - 打开 Web 应用以看起来像一个独立的原生应用。此模式下,用户代理将排除诸如 URL 栏等标准浏览器 UI 元素,但可以包括诸如状态栏和系统返回按钮的其他系统 UI 元素。
    • Minimal-ui - 此模式类似于 fullscreen,但为终端用户提供了可访问的最小 UI 元素集合,例如,后退按钮、前进按钮、重载按钮以及查看网页地址的一些方式。
    • Browser - 使用操作系统内置的标准浏览器来打开 Web 应用。 (默认参数)

      引入

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Progressive Times</title>
<link rel="manifest" href="/manifest.json">
</head>
<body>
..content goes here..
</body>
</html>

添加到主屏幕条件

显示“添加到主屏幕”提示,需要满足以下几个条件:

  • 需要 manifest.json 文件
  • 清单文件需要启动 URL
  • 需要 144x144 的 PNG 图标
  • 网站正在使用通过 HTTPS 运行的 Service Worker
  • 用户需要至少浏览网站两次,并且两次访问间隔在五分钟之上

控制浏览器的添加到主屏幕事件

当你不希望浏览器的添加到主屏幕提示时

1
2
3
4
window.addEventListener('beforeinstallprompt', function(e) {
e.preventDefault();
return false;
});

判断用户对该功能的选择情况

1
2
3
4
5
6
7
8
9
10
window.addEventListener('beforeinstallprompt', function (event) {
event.userChoice.then(function (result) {
console.log(result.outcome);
if (result.outcome == 'dismissed') {
// 发送数据以进行分析
} else {
// 发送数据以进行分析
}
});
});

为 beforeinstallprompt 事件添加了监听器。这个事件有个叫做 userChoice 的对象,它返回用户决定的 Promise 。我们可以使用这个 Promise 的结果来判断用户是关掉提示还是确认提示。

此时,你可以决定将此信息发送到 Web 分析工具,以便随着时间的推移跟踪此功能的使用情况。这项技术可以用于了解用户如何与“添加到主屏幕”提示进行交互。

控制提示

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
43
44
45
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Progressive Times</title>
</head>
<body>
<button id="btnSave" disabled>Click this to show the prompt</button>
</body>
<script>
window.addEventListener('load', function () {
var btnSave = document.getElementById('btnSave');
var savedPrompt;
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js').then(function (registration) {
// 注册成功
console.log('ServiceWorker registration successful with scope: ',
registration.scope);
}).catch(function (err) {
// 注册失败 :(
console.log('ServiceWorker registration failed: ', err);
});
}
window.addEventListener('beforeinstallprompt', function (e) {
e.preventDefault();
btnSave.removeAttribute('disabled');
savedPrompt = e;
return false;
});
btnSave.addEventListener('click', function () {
if (savedPrompt !== undefined) {
savedPrompt.prompt();
savedPrompt.userChoice.then(function (result) {
if (result.outcome == 'dismissed') {
console.log('User dismissed homescreen install');
} else {
console.log('User added to homescreen');
}
savedPrompt = null;
});
}
});
});
</script>
</html>
  • 点击此按钮会显示提示
  • 检查是否支持 Service Workers,如果支持则注册
  • 为 ‘beforeinstallprompt’ 事件添加事件监听器
  • 此时,我们可以启用按钮
  • 我们将事件保存在变量中,这样它可以稍后触发
  • 为按钮的点击事件添加事件监听器
  • 用户与我们的应用进行了积极的互动,Chrome 已经尝试提前提醒,所以让我们来看看提示
  • 遵循用户的选择
  • 我们不再需要提示,清理掉它

调试清单文件

支持pwa技术网站:https://www.flipkart.com/

  • 可以通过Google Chrome中的Application标签中的Manifest菜单调试
  • 通过在线网站调试 https://manifest-validator.appspot.com/
  • 测试网址:https://hub.settled.co.uk/offline

    需要梯子访问

pwa 入门实践-Service Workers

发表于 2018-04-18

Service Workers

定义

Service Workers 主要是通过对本网站中所有的HTTP请求进行拦截,并对期进行缓存控制或者响应控制。

引入

Service Worker 其实就是后台线程中运行的javascript文件,所以引入的方式与其他js文件相同

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>The best web page ever</head>
<body>
<script>
// 注册 service worker
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("/sw.js")
.then(function(registration) {
// 注册成功
console.log(
"ServiceWorker registration successful with scope: ",
registration.scope
);
})
.catch(function(err) {
// 注册失败 :(
console.log("ServiceWorker registration failed: ", err);
});
}
</script>
</body>
</html>

即

  • 检查当前浏览器是否支持 Service Workers
  • 如果支持,注册一个叫做 ‘sw.js’ 的 Service Worker 文件
  • 如果成功则打印到控制台
  • 如果发生错误,捕获错误并打印到控制台

然后我们在注册的sw.js文件中添加一下内容

1
2
3
4
5
self.addEventListener('fetch', function(event) {     
if (/\.jpg$/.test(event.request.url)) {
event.respondWith(fetch('/images/unicorn.jpg'));
}
});

  • 为 fetch 事件添加事件监听器
  • 检查传入的 HTTP 请求是否是 JPEG 类型的图片
  • 尝试获取独角兽的图片并用它作为替代图片来响应请求

以上我们就成功的在浏览器中通过注册Service Workers的方式代理了本网站的所有请求。并选择我们需要控制的请求,返回特定的响应结果

> 需要注意的是,使用Service Worker 技术一定要https协议才可以,主要是怕被恶意注册非法Service Worker使网站全部请求被劫持。不过本地调试的时候访问localhost不受限制

控制缓存

预缓存

我们可以再 Service Workers 加载的时候,缓存你想要的资源。即用户首次访问本网站, Service Workers会下载并安装自己,我们可以再这个过程中将需要的内容(例如:常用的静态资源)加载好。

eg:

1
2
3
4
5
6
7
8
9
10
var cacheName = 'helloWorld';                
self.addEventListener('install', event => {
event.waitUntil(
caches.open(cacheName)
.then(cache => cache.addAll([
'/js/script.js',
'/images/hello.png'
]))
);
});

  • 首先为缓存创建一个名称cacheName(方便以后对缓存进行精准控制)
  • 进入Service Workers的安装事件中
  • 使用我们指定的缓存名称来打开缓存
  • 把需要的js文件和图片文件添加到缓存中

需要注意的是:在缓存文件下载的过程中,任何文件下载失败都会导致安装过程的失败,使得Servicer Worker安装失败

监听缓存

让 Service Worker 开始监听 fetch 事件,如果遇到了匹配的的资源请求,则自动从缓存中获取内容

1
2
3
4
5
6
7
8
9
10
self.addEventListener("fetch", function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.request);
})
);
});
  • 添加 fetch 事件的事件监听器
  • 检查传入的请求 URL 是否匹配当前缓存中存在的任何内容
  • 如果有 response 并且它不是 undefined 或 null 的话就将它返回
  • 否则只是如往常一样继续,通过网络获取预期的资源

    拦截请求同时缓存

    一个请求被捕获的时候,首先检查请求的资源是否存在于缓存之中。如果存在,我们可以就此返回缓存并不再继续执行代码。

如果请求的资源于缓存之中没有的话,我们就重新发起网络请求。然后,我们需要检查 HTTP 响应,确保服务器返回的是成功响应并且没有任何问题。

如果成功响应,我们会再次克隆响应。你可能会疑惑我们为什么需要再次克隆响应

最后,将这个这个响应的结果添加至缓存中,以便下次再使用它。如果用户刷新页面或访问网站另一个请求了这些资源的页面,它会立即从缓存中获取资源。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var cacheName = "helloWorld";
self.addEventListener("fetch", function(event) {
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
var requestToCache = event.request.clone();
return fetch(requestToCache).then(function(response) {
if (!response || response.status !== 200) {
return response;
}
var responseToCache = response.clone();
caches.open(cacheName).then(function(cache) {
cache.put(requestToCache, responseToCache);
});
return response;
});
})
);
});
  • 自定义缓存的名称
  • 为 fetch 事件添加事件监听器以拦截请求
  • 当前请求是否匹配缓存中存在的任何内容?
  • 如果匹配的话,就此返回缓存并不再继续执行
  • 这很重要,我们克隆了请求。请求是一个流,只能消耗一次。
  • 尝试按预期一样发起原始的 HTTP 请求
  • 如果由于任何原因请求失败或者服务器响应了错误代码,则立即返回错误信息
  • 再一次,我们需要克隆响应,因为我们需要将其添加到缓存中,而且它还将用于最终返回响应
  • 打开名称为 “helloWorld” 的缓存
  • 将响应添加到缓存中

处理额外的查询参数

当 Service Worker 检查已缓存的响应时,它使用请求 URL 作为键。默认情况下,请求 URL 必须与用于存储已缓存响应的 URL 完全匹配,包括 URL 查询部分的任何字符串。

如果对文件发起的 HTTP 请求附带了任意查询字符串,并且查询字符串会更改,这可能会导致一些问题。例如,如果你对一个先前匹配的 URL 发起了请求,则可能会发现由于查询字符串略有不同而导致该 URL 找不到。当检查缓存时想要忽略查询字符串,使用 ignoreSearch 属性并设置为 true 。

eg:

1
2
3
4
5
6
7
8
9
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.match(event.request, {
ignoreSearch: true
}).then(function (response) {
return response || fetch(event.request);
})
);
});

其他选项:

  • ignoreMethod:忽略请求方法
  • ignoreVary:忽略请求中的vary首部

pwa 入门实践-概念阐述

发表于 2018-04-17

PWA

本文章理论部分参考于 Progressive Web Apps (PWA) 中文版 一书

定义

PWA为渐进式网络应用 ( Progressive Web Apps )的缩写,更通俗的解释即为:可以离线加载内容的一种特殊网站,为什么要叫渐进式呢,主要是由于PWA的特点,在不支持的设备上浏览时,回加载传统的网站形式,如果设备支持的话,则可以通过缓存控制等等方式来实现更快的加载,离线数据等功能的PWA 应用(网站)

优点

利用PWA技术的网站有以下优点:

  • 渐进式
  • 可以离线加载部分内容
  • 更可控的缓存机制
  • 安全性高
  • 类似原生的体验(可以在主屏幕放置入口,自定义的图标,消息推动,自定义首屏,自定义的报错提示)
  • 节省资源,以及更快的打开速度(利用缓存机制)
  • 避免了类似app的审核过程(例如苹果商店,谷歌商店)

技术要点

可以做到以上的优势,主要是由于以下几种技术

  • Service Workers
  • manifest(清单文件)

下面我们对这些关键技术点进行展开阐述

VuePress-基于vue-ssr的静态网站生器初体验

发表于 2018-04-16

VuePress

昨天在微博上看到尤大神新发布的基于vue-ssr静态网站生成器VuePress,刚刚通过Hexo搭建博客的我又忍不住去尝试了下。。

参考官方文档可知该项目有一下特点:

  • 内置markdown(基础功能)
  • 支持PWA
  • 集成了Google Analytics
  • 拥有一套默认主题(风格与(官方文档)[https://vuepress.vuejs.org]一致)
  • 自动生成的GitHub链接和页面编辑链接

快速上手

安装

初始化项目

1
npm init -y

安装 vuepress,也可以全局安装

1
npm install -D vuepress

创建文章文件夹

1
mkdir docs

配置package.json

1
2
3
4
5
6
{
"scripts": {
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
}
}

书写

直接在docs文件夹下新建markdown文件即可编辑书写文章

预览

1
npm run docs:dev

打开
http://localhost:8080/

构建

1
npm run docs:build

生成的文件默认会在 .vuepress/dist 文件夹下

自定义配置

可以将配置文件写到 .vuepress/config.js 中

添加顶部导航

1
2
3
4
5
6
7
8
9
module.exports = {
themeConfig: {
nav: [
{ text: 'Home', link: '/' },
{ text: 'Guide', link: '/guide/' },
{ text: 'External', link: 'https://google.com' },
]
}
}

添加侧边栏

1
2
3
4
5
6
7
8
9
module.exports = {
themeConfig: {
sidebar: [
'/',
'/page-a',
['/page-b', 'Explicit link text']
]
}
}

同时支持分组添加侧边栏
eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
themeConfig: {
sidebar: [
{
title: 'Group 1',
collapsable: false,
children: [
'/'
]
},
{
title: 'Group 2',
children: [ /* ... */ ]
}
]
}
}

自定义主题

可以在github上复制官方的主题源码到.vuepress/theme中,然后使用

1
vuepress eject 目标路径

命令自定义主题

部署到github上,生成专属博客

在 .vuepress/config.js 中设置基础路径

即如果你的github连接为:https://github.com/foo/bar

你的主页为:
https://foo.github.io/bar/

那么你的基础路径设置为:bar即可

最后构建文件之后,进入到生成文件路径

1
cd docs/.vuepress/dist

将dist文件夹中的代码提交到对应的git仓库就好

下面访问你的地址就好了:https://xxx.github.io

webstrom 激活码

发表于 2018-04-16

webstrom 激活

打开WebStorm发现之前输入的License Server没法用了,不能通过WebStorm的检测,搜索良久,终于找到了最新版本WebStorm的破解方法。

  在激活页面选择License Server,输入:http://idea.codebeta.cn,点击Activate即可激活。

JetBrains 家的很多ide都可以尝试用此激活

npm script 工作流

发表于 2018-04-12

npm script

本文章系列来自于对掘金小册的npm-script一书的内容整理,欢迎大家支持正版

快速创建npm项目

执行npm init 初始化命令,生成package.json工程描述文件

1
2
3
4
5
6
7
8
9
10
npm init

package name: 包名称
version: 版本号
description: 描述信息
entry point: 入口文件
test command: 测试命令
git repository: 仓库地址
keywords: 关键字
license: 许可协议

也可以通过 -f -y 命令跳过问答快速生成package.json

1
2
3
4
// -force
npm init -f
// -yes
npm init -y

可以通过以下命令自定义初始化配置

1
2
3
4
5
npm config set init.author.email "wangshijun2010@gmail.com"
npm config set init.author.name "wangshijun"
npm config set init.author.url "http://github.com/wangshijun"
npm config set init.license "MIT"
npm config set init.version "0.1.0"

npm run 执行命令

使用npm run xxx 可以执行写在package.json文件中 “scirps” 里面的命令
eg:

1
2
3
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},

在执行 npm run xxx 之前,npm会将node_modules/.bin添加到环境变量 $PATH的前面,也就是所有可执行文件的npm依赖都可以直接在 npm script 中直接调用,无需在npm script 中加入完整路径 eg:”./node_modules/.bin/xxxx **.js”

多个npm script串行执行

可以在配置命令的时候,采用 && 符号链接不同的命令,执行时会严格按照先后顺序执行

eg:

1
2
3
"scripts": {
"test": "npm run lint:js && npm run lint:css && npm run lint:json && npm run lint:markdown && mocha tests/"
},

同时如果执行过程中遇到了错误后面命令也会停止执行

多个npm script并行执行

需要同时给出结果的一些场景,可能需要并行执行,即把 && 符号换成 & 即可

1
2
3
"scripts": {
"test": "npm run lint:js & npm run lint:css & npm run lint:json & npm run lint:markdown & mocha tests/"
},

对于子命令中长进程处理

由于不同情况下不同自命令的执行时间不同,同时发送多条异步请求,需要等待请求执行完成之后再处理。通过命令中增加 & wait 解决
eg:

1
npm run lint:js & npm run lint:css & npm run lint:json & npm run lint:markdown & mocha tests/ & wait

加上wait之后,过长的进程就可以通过 command + C 命令结束进程

可以通过下载npm install npm-run-all 更加简洁的配置多命令运行,参考官方文档

为 npm script传递参数

一些命令在执行的时候需要一些执行参数
eg: eslint 内置的自动修复模式,需要传入 –fix参数,在scripts中声明执行的时候也可能需要这些命令,有两种添加方式

  • 第一种: 建立新的带参数命令

    1
    2
    "lint:js": "eslint *.js",
    "lint:js:fix": "eslint *.js --fix",
  • 第二种: 引用之前的无参数命令,并为之传递参数

    1
    2
    "lint:js": "eslint *.js",
    "lint:js:fix": "npm run lint:js -- --fix",

–fix 参数前面的 – 意思是要给前面的npm run lint:js 实际指向的命令传递额外的参数。

给 npm script 添加注释

添加注释可以再命令执行时优化log记录,也可以帮助标识命令的含义,一共有两种做法,推荐后者

  • 方法1:
    1
    2
    "//": "运行所有代码检查和单元测试",
    "test": "npm-run-all --parallel lint:* mocha"

声明一个// 为key的命令,npm会自动忽略该键,但是声明多个的时候最后只会展示最后一个
Alt text

  • 方法2:
    1
    "test": "# 运行所有代码检查和单元测试 \n    npm-run-all --parallel lint:* mocha"

注意注释后面的换行符 \n 和多余的空格,换行符是用于将注释和命令分隔开,这样命令就相当于微型的 shell 脚本,多余的空格是为了控制缩进,也可以用制表符 \t 替代。这种做法能让 npm run 列出来的命令更美观
test

调整 npm script 日志输出

显示尽可能少的信息

调用 npm script 的时候添加 –loglevel silent 、–silent 或者 -s 参数

显示尽可能多的运行时状态

当我们在排查问题得时候需要较详细的log日志
使用 –loglevel verbose 、 –verbose 或者更简单的 -d 参数

npm script 钩子

npm run xxx的命令执行的时候分三个阶段

  • 检查 scripts对象中是不是存在 prexxx命令,如果有先执行该命令
  • 检查是否有 xxx 命令,有的话运行 test 命令,没有的话报错
  • 检查是否存在 postxxx 命令,如果有,执行 posttest 命令

利用这点我们可以再自动化测试之后增加测试覆盖率的判定,即写在postxxx命令当中,然后利用open工具打开
eg:

  • precover,收集覆盖率之前把之前的覆盖率报告目录清理掉;
  • cover,直接调用 nyc,让其生成 html 格式的覆盖率报告;
  • postcover,清理掉临时文件,并且在浏览器中预览覆盖率报告;

npm 中的环境变量

获得变量

我们可以拿到完整的环境变量

1
npm run env

也可以通过 npm run env | grep npm_package | sort 命令筛选拿到预定义的环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 作者信息...
npm_package_author_email=wangshijun2010@gmail.com
npm_package_author_name=wangshijun
npm_package_author_url=http://github.com/wangshijun
// 依赖信息...
npm_package_devDependencies_markdownlint_cli=^0.5.0
npm_package_devDependencies_mocha=^4.0.1
npm_package_devDependencies_npm_run_all=^4.1.2
// 各种 npm script
npm_package_scripts_lint=npm-run-all --parallel lint:*
npm_package_scripts_lint_css=stylelint *.less
npm_package_scripts_lint_js=eslint *.js
npm_package_scripts_lint_js_fix=npm run lint:js -- --fix
npm_package_scripts_lint_json=jsonlint --quiet *.json
// 基本信息
npm_package_version=0.1.0
npm_package_gitHead=3796e548cfe406ec33ab837ac00bcbd6ee8a38a0
npm_package_license=MIT
npm_package_main=index.js
npm_package_name=hello-npm-script
npm_package_readmeFilename=README.md
// 依赖的配置
npm_package_nyc_exclude_0=**/*.spec.js
npm_package_nyc_exclude_1=.*.js...

使用变量

变量的使用方法遵循 shell 里面的语法,直接在 npm script 给想要引用的变量前面加上 $ 符号即可
eg:

1
2
3
{
"dummy": "echo $npm_package_name"
}

使用场景

比如需要把收集分析的报告信息,按照版本号进行分档管理

1
2
3
4
5
6
7
8
"scripts": {
- "precover": "rm -rf coverage",
"cover": "nyc --reporter=html npm test",
- "postcover": "rm -rf .nyc_output && opn coverage/index.html"
+ "cover:cleanup": "rm -rf coverage && rm -rf .nyc_output",
+ "cover:archive": "mkdir -p coverage_archive/$npm_package_version && cp -r coverage/* coverage_archive/$npm_package_version",
+ "postcover": "npm run cover:archive && npm run cover:cleanup && opn coverage_archive/$npm_package_version/index.html"
}

此时:
cover:archive 做了 2 件事情:

  • mkdir -p coverage_archive/$npm_package_version 准备当前版本号的归档目录;
  • cp -r coverage/* coverage_archive/$npm_package_version,直接复制文件来归档;…

自定义变量

例如生成的报告需要与其他同事约定一个服务器端口号,并利用http-server启动一个轻量级服务来在线展示报告

1
2
3
4
5
6
7
8
9
10
11
12
"version": "0.1.0",
+ "config": {
+ "port": 3000
+ },
"scripts": {
@@ -15,7 +18,9 @@
"cover": "nyc --reporter=html npm test",
- "postcover": "npm run cover:archive && npm run cover:cleanup && opn coverage_archive/$npm_package_version/index.html"
+ "cover:serve": "http-server coverage_archive/$npm_package_version -p $npm_package_config_port",
+ "cover:open": "opn http://localhost:$npm_package_config_port",
+ "postcover": "npm-run-all cover:archive cover:cleanup --parallel cover:serve cover:open"
},...

引用自定义变量的格式为:
$npm_package_config_port
即可拿到自定义的端口号 3000

npm 自动命令补全

暂时跳过

##

千里之行,始于足下

发表于 2018-04-12

曾经折腾过很多的博客,后来一直在用简书,但是有的东西发了还要经过审核,封过两次号。。。想想还是算了。最终选择了Hexo,毕竟还能给github刷刷绿点。有问题参考Hexo官方文档,具体构建的细节可以参考这篇文章

记录常用的Hexo命令

创建新文章

1
$ hexo new "My New Post"

更多信息: 写作

运行本地服务

1
$ hexo server

更多信息: 服务

生成静态文件

1
$ hexo generate

更多信息: 生成

提交构建代码

1
$ hexo deploy

更多信息: 构建

感谢iissnan的NEXT主题很好用,在此感谢并推荐大家使用!

lvkunpeng

9 日志
2 标签
GitHub E-Mail
© 2018 lvkunpeng
由 Hexo 强力驱动 v3.7.1
|
主题 — NexT.Pisces v6.1.0