Taohong的博客


  • Home

  • Archives

npm npx 使用指南

Posted on 2018-04-27 | In 技术

npm npx 使用指南

npm

原理

npm 脚本的原理非常简单。每当执行 npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。

比较特别的是,npm run 新建的这个 Shell,会将当前目录的 node_modules/.bin 子目录加入 PATH 变量,执行结束后,再将PATH变量恢复原样。

这意味着,当前目录的 node_modules/.bin 子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写 mocha test 就可以了。

1
"test": "mocha test"

而不用写成下面这样。

1
"test": "./node_modules/.bin/mocha test"

执行顺序

如果是并行执行(即同时的平行执行),可以使用 & 符号。

1
npm run script1.js & npm run script2.js

如果是继发执行(即只有前一个任务成功,才执行下一个任务),可以使用 && 符号。

1
npm run script1.js && npm run script2.js

钩子

npm 脚本有pre和post两个钩子。举例来说,build脚本命令的钩子就是prebuild和postbuild。

1
2
3
"prebuild": "echo I run before the build script",
"build": "cross-env NODE_ENV=production webpack",
"postbuild": "echo I run after the build script"

用户执行npm run build的时候,会自动按照下面的顺序执行。

1
npm run prebuild && npm run build && npm run postbuild

因此,可以在这两个钩子里面,完成一些准备工作和清理工作。下面是一个例子。

1
2
3
"clean": "rimraf ./dist && mkdir dist",
"prebuild": "npm run clean",
"build": "cross-env NODE_ENV=production webpack"

常用脚本示例

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
// 删除目录
"clean": "rimraf dist/*",

// 本地搭建一个 HTTP 服务
"serve": "http-server -p 9090 dist/",

// 打开浏览器
"open:dev": "opener http://localhost:9090",

// 实时刷新
"livereload": "live-reload --port 9091 dist/",

// 构建 HTML 文件
"build:html": "jade index.jade > dist/index.html",

// 只要 CSS 文件有变动,就重新执行构建
"watch:css": "watch 'npm run build:css' assets/styles/",

// 只要 HTML 文件有变动,就重新执行构建
"watch:html": "watch 'npm run build:html' assets/html",

// 部署到 Amazon S3
"deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/",

// 构建 favicon
"build:favicon": "node scripts/favicon.js",

npx

执行依赖包里的二进制文件

举例来说,之前我们可能会写这样的命令:

1
2
npm i -D webpack
./node_modules/.bin/webpack -v

有了 npx,你只需要这样

1
2
npm i -D webpack
npx webpack -v

npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你临时安装(one-off commands)

这条命令会临时安装 create-react-app 包,命令完成后 create-react-app 会删掉,不会出现在 global 中。下次再执行,还是会重新临时安装。

1
$ npx create-react-app my-cool-new-app

再比如 npx http-server 可以一句话帮你开启一个静态服务器

1
$ npx http-server

运行远程仓库的可执行文件

1
npx github:piuccio/cowsay hello

运行不同Node.js版本的命令

1
npx node@6 -v

参考链接
阮一峰的网络日志>npm scripts 使用指南

介绍npx:一个npm包执行器
npx 是什么

vuePress vue驱动的静态站点生成工具

Posted on 2018-04-25 | In 技术

vuePress vue驱动的静态站点生成工具

起步

全局安装

1
2
3
4
5
6
7
8
9
10
11
# 全局安装
yarn global add vuepress # 或 npm install -g vuepress

# 创建一个 markdown 文件
echo '# Hello VuePress' > README.md

# 开始编写文档
vuepress dev

# 构建
vuepress build

在已有项目中安装

如果你想要在一个已有项目中维护文档,就应该将 VuePress 安装为本地依赖。此设置还允许你使用 CI 或 Netlify 服务,在推送时自动部署。

1
2
3
4
5
6
7
# 安装为本地依赖项
yarn add -D vuepress # 或 npm install -D vuepress

# 创建一个 docs 目录
mkdir docs
# 创建一个 markdown 文件
echo '# Hello VuePress' > docs/README.md

然后,给 package.json 添加一些 scripts 脚本:

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

主页(Homepage)

默认主题提供了一个主页布局(用于该网站的主页)。要使用它,需要在你的根目录 README.md 的 YAML front matter 中指定 home:true,并加上一些其他的元数据。这是本网站使用的实际数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
home: true
heroImage: /hero.png
actionText: 起步 →
actionLink: /guide/
features:
- title: 简明优先
details: 对以 markdown 为中心的项目结构,做最简化的配置,帮助你专注于创作。
- title: Vue 驱动
details: 享用 Vue + webpack 开发环境,在 markdown 中使用 Vue 组件,并通过 Vue 开发自定义主题。
- title: 性能高效
details: VuePress 将每个页面生成为预渲染的静态 HTML,每个页面加载之后,然后作为单页面应用程序(SPA)运行。
footer: MIT Licensed | Copyright © 2018-present Evan You
---

YAML front matter 的内容之后的其他任意内容,将被解析为正常 markdown,并在 features 部分之后渲染。

如果你想彻底自定义主页的布局,你还可以使用自定义布局

导航链接(navbar links)

你可以通过 themeConfig.nav 将链接添加到导航栏中:

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

文档链接

官网

中文文档

参考项目

单元测试

Posted on 2018-04-23 | In 技术

单元测试方法

TDD
测试驱动开发

BDD
行为驱动开发

单元测试工具

  • 测试框架
  • 断言库
  • mock库
  • test runner
  • 覆盖率工具

测试框架

  • Qunit
  • jasmine
  • mocha
  • intern

断言库

  • chai
  • should
  • expect
  • assert

mock库

  • sinon

测试用例

测试用例(Test Case)是为某个特殊目标而编制的一组测试输入、执行条件以及预期结果,以便测试某个程序路径或者核实是否满足某个特定需求。

test runner

提供执行环境,管理执行流程

  • Karma
  • buster.js

覆盖率工具

  • Istanbul

前端测试用例分类

  • 数据层
  • 逻辑层
  • 展示层
  • 工具类

版本管理

Posted on 2018-04-20 | In 技术

分支模型

什么是分支模型

  • 分支:
    从目标仓库获得一份项目拷贝,每条拷贝都有和原仓库功能一样的开发线
  • 分支模型(branching model)/工作流(workflow):
    一个围绕项目[开发/部署/测试]等工作流程的分支操作(创建,合并等)规范集合

产品级的分支模型

常驻分支

  • development
    从master创建
  • production(master)
    默认分支

活动分支

  • feature
    从development创建
  • hotfix: 如hotfix-36
    从master创建
  • release: release-110
    从development创建

工程规范

Posted on 2018-04-19 | In 技术

工程规范

如何制定规范

  1. 参考业界规范
  2. 民主讨论
  3. 结果导向
  4. 不断完善

一般的规范在业界的大公司中已经有了成熟的方案。我们可以直接拿来参考

规范始终是给自己团队用的,需要的经过集体讨论。

实现规范的方式应该只注意结果,至于过程不需要硬性规定。

规范不可能一簇而就,需要不断完善。

规范管理工具

  • htmllink
  • stylelink
  • eslink

移动页面开发

Posted on 2018-04-02 | In 技术

基于APP的移动页面开发

如何唤醒app

URL Scheme:一个可以让app相互之间可以跳转的协议
UniversalLink:通过传统http链接来启动app的技术,可以使用相同的网址打开网站和app

浏览器中唤起native app

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
_openApp(openUrl, callback) {
var iframe = document.createElement('iframe');
iframe.src = openUrl;
var body = document.body;
body.appendChlid(iframe);
setTimeout(()=>{
body.removeChild(iframe)
callback && callback(1)
}, 800)
},
appGo(openUrl, downUrl) {
this._openApp(openUrl, (opened) => {
if (opened) {
console.log('app awake success')
} else {
window.location.href = downUrl
}
})
}
}

如何和app进行数据交互

jsBridge

移动端性能优化

  1. 首屏优化
  2. 白屏时间
  3. 可交互时间
  4. 完全加载时间

定位性能问题

首屏时间 = DNS时间 + 建立连接时间 + 后端相应时间 + 网络传输时间 + 首屏页面渲染时间

移动端的一些坑

1px

用scale

慎用fixed

使用绝对定位代替

transition闪屏

1
2
3
4
5
6
body {
/*设置内嵌的元素在 3D 空间如何呈现:保留3D */
-webkit-transform-style: preserve-3d;
/* 设置进行转换的元素的背面在面对用户时是否可见:隐藏 */
-webkit-backface-visibility:hidden;
}

计时器 暂停

  • 放入后台任务,用websocket进行传输(这是最方便快捷的方法)
  • 把定时器函数里的时间累加逻辑,换成每次都从系统时间获取。
  • 使用监听事件visibilitychange,当监听到离开页面时,使js动画暂停,回来后继续

active失效

1
2
3
4
5
6
7
8
<style>
a{color:#000;}
a{color:#fff;}
</style>
<a href="#">btn</a>
<script>
document.addEventListener('touchstart', function () {})
</script>

页面滚动

overflow的滚动效果不佳,用-webkit-overflow-scrolling代替

1
2
/* 当手指从触摸屏上移开,会保持一段时间的滚动 */
html {-webkit-overflow-scrolling: touch; }

webpack环境配置

Posted on 2018-03-26

webpack 环境配置

搭建开发环境主要有三种

  1. webpack watch mode
  2. webpack-dev-server
  3. express + webpack-dev-middleware(更灵活,但是需要更多配置)

webpack watch mode

清除打包内容

clean-webpack-plugin

webpack dev server

  1. live reloading(自动刷新浏览器)
  2. 不能打包文件
  3. 路径重定向
  4. https
  5. 浏览器中显示编译错误
  6. 接口代理
  7. 模块热更新

devServer
inline
contentBase
port
historyApiFallback
https
proxy
hot
openpage
lazy
overlay

historyApiFallback

对于单页面程序,浏览器的brower histroy可以设置成html5 history api或者hash,而设置为html5 api的,如果刷新浏览器会出现404 not found,原因是它通过这个路径(比如: /activities/2/ques/2)来访问后台,所以会出现404,而把historyApiFallback设置为true那么所有的路径都执行index.html

代理远程接口

proxy

代理远程接口请求

使用的是 http-proxy-middleware

options

配置选项 说明
target 代理地址
changeOrigin 改变你的源到这个url
headers http请求头
logLevel 调试用的
pathRewrite 重定向接口请求

模块热更新

Module Hot Reloading

  • 保持应用的数据状态
  • 节省调试时间
  • 样式调试更快

如何设置

  • devServer.hot
  • webpack.HotModuleReplacementPlugin
  • webpack.NamedModulesPlugin(查看模块的相对路径)

热门框架都有相应的热更新loader

开启调试 SourceMap

设置 ESLink 检查代码格式

区分开发环境 和 生产环境

  • 开发环境
    • 模块热更新
    • sourceMap
    • 接口代理
    • 代码规范检查
  • 生产环境
    • 提取公共代码
    • 压缩混淆
    • 文件压缩 或是 Base64 编码
    • 去除无用的代码

共同点

  • 同样的入口哦
  • 同样的代码处理(loader处理)
  • 同样的解析配置

如何做
webpack-merge
webpack.dev.conf.js
webpack.prod.conf.js
webpack.common.conf.js

使用 middleware 来搭建开发环境

更灵活

css小技巧

Posted on 2018-03-17
  1. 移动端使用overflow-y: auto; 可以隐藏滚动条
1
2
3
4
body {
overflow-y: auto;
height: 100%;
}

webpack使用场景总结

Posted on 2018-03-14 | In 技术

webpack使用总结

webpack 有四个核心概念

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)

下面主要讲解常见应用场景的配置

使用webpack方式

  1. webpack命令
  2. webpack配置
  3. 第三方脚手架

编译 ES6

语法

“babel-core”: “^6.26.0”
“babel-loader”: “^7.1.4”
“babel-preset-env”: “^1.6.1”

函数和方法

  • Babel Polyfill

全局垫片 为应用准备

1
npm install babel-polyfill --save
1
import 'babel-polyfill'
  • Babel Runtime Transform

局部垫片 为开发框架准备

1
2
npm install babel-plugin-transform-runtime --save-dev
npm install babel-runtime --save

在 .babelrc中配置

1
2
3
4
5
6
7
8
9
10
{
"presets": [
["@babel/preset-env", {
"targets": {
"borwsers": ["> 1%", "last 2 versions"]
}
}]
],
"plugins" :["@babel/transform-runtime"]
}

编译 Typescript

typesript-loader

  • 安装

    1
    2
    3
    npm i typescipt ts-loader  --save-dev
    // 或者
    npm i typescipt awesome-typescript-loader --save-dev
  • 配置

    1
    2
    tsconfig.json
    webpack.config.js

提取公共代码

配置

  1. webpack3

    链接地址

  2. webpack4

    webpack 4 移除 CommonsChunkPlugin,取而代之的是两个新的配置项(optimization.splitChunks 和 optimization.runtimeChunk)

    默认模式是经过千挑万选的,可以用于满足最佳web性能的策略。

    没有了CommonsChunkPlugin,咱拿什么来分包

    精读《webpack4.0 升级指南》

场景

  • 单页应用
  • 单页应用 + 第三方依赖
  • 多页应用 + 第三方依赖 + webpack生成代码

代码分割 和 懒加载

webpack methods (webpack内置方法)

require.ensure

require.include

ES 2015 Loader spec (2015 loader 规范)

1
import()

处理CSS style-loader

引入

style-loader

  1. style-loader
  2. style-loader/url
  3. style-loader/useable

Style-loader 可以使得我们把css 通过style 标签引入到我们的html 中去

Style-loader/url 可以让我们把css 通过 link 标签引入到我们的 html 中去

css-loader

options

配置选项 说明
alias 解析的别名
importLoader @import
Minimize 是否压缩
modules 启用css-modules

如果设置了 root 查询参数,那么此查询参数将被添加到 URL 前面,然后再进行转译。
要禁用 css-loader 解析 url(),将选项设置为 false。

CSS modules

  1. :local
  2. :global
  3. compose
  4. compose … from path

localIdentName: '[path][name]__[local]--[hash:base64:5]'

配置 less / sass

1
2
npm install less-loader less  --save-dev
npm install sass-loader node-sass --save-dev

提取 CSS 代码

  1. extract-loader
  2. ExtractTextWebpackPlugin
1
2
3
4
5
// webpack3
npm install extract-text-webpack-plugin --save-dev

// webpack4
npm install extract-text-webpack-plugin@next --save-dev

PostCSS

转换css

Autoprefixer

CSS-nano

CSS-next

Tree Shaking

JS Tree Shaking

CSS Tree Shaking

文件处理

图片处理

  1. css中引入的图片
  2. 自动合成雪碧图
  3. 压缩图片
  4. base64 编码

file-loader(引入图片)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
publishPath: '',
outputPath: '',
useRelativePath: true
}
}
]
}
]
}

url-loader(base64 编码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 5000,
publishPath: '',
outputPath: '',
useRelativePath: true
}
}
]
}
]
}
}

img-loader(压缩图片)
链接地址

img-loader 是一个插件的集合,查看配置选项要到相应的插件中去看

1
2
3
4
5
6
{
loader: 'url-loader',
options: {
pngquant: 80
}
}

postcss-sprites(合成雪碧图)

1
2
3
4
5
6
7
8
9
10
11
12
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('postcss-sprites')({
spritePath: 'dist/assets/imgs/sprites',
retina: true
})
]
}
}

字体文件

1
2
3
4
5
6
7
8
9
{ test: /\.(eot|woff2?|ttf|svg)/
user: 'url-loader',
options: {
limit: 5000,
publishPath: '',
outputPath: '',
useRelativePath: true
}
}

第三方js库

webpack.ProvidePlugin

1
2
3
4
5
6
7
8
9
10
11
12
plugins: [
new webpack.ProvidePlugin({
jquery$: 'jquery'
})
]

// 本地文件
resolve: {
alias: {
jquery$: path.resolve(__dirname, 'src/libs/jquery.min.js')
}
}

import-loader

1
2
3
4
5
6
7
{
test: path.resolve(__dirname, 'src/app.js')
user: 'imports-loader',
options: {
jquery$: 'jquery'
}
}

window

生成 html

链接

判断是否应该写成一个组件的条件

Posted on 2018-01-30 | In 技术

判断是否应该写成一个组件的条件

判断是否应该写成一个组件还是两个组件要看几个方面:

  1. 看内容,如果内容相同,那么最好是写成一个组件,再通过状态控制不同的展现方式
  2. 复杂度,如果要让一个组件兼顾多种展现情况,而过度重构,那就得不偿失了,复杂度是构建组件的一个指标
  3. 重用度,如果一个组件仅仅使用一次,那么是否抽组件就不是first level thing,如果重用度非常的高,那么就需要优先考虑这个问题了
1…345…8

Taohong

记录前端技术,学习心得与生活感悟

80 posts
6 categories
65 tags
© 2020 Taohong
Powered by Hexo
|
Theme — NexT.Muse v5.1.4