Archives for : Nodejs

next.js 的一些坑

971bf7f8-9ac0-11e6-975c-188defd82df1

这阵子在折腾 next.js,用来做 node 服务端渲染真心不错,然而一路捣腾下来,坑也是不少,有四个比较大的坑。

  1. isomorphic-fetch(解决)
  2. node 端代码打包(未解决)
  3. js 放到 cdn 或者 oss(解决)
  4. static 目录下的图片 hash(临时方案)

这四个坑,1 和 3 是必须解决的,2 和 4 可选。

1

fetch 本来不是什么问题,但是涉及到请求签名,就来了点麻烦,需要区分是服务端还是客户端,客户端用 cookie 存储 token,服务端用变量。

2

node 代码其实不需要打包,因为是运行在服务端,不过为了节省 docker 镜像的大小,尝试了打包,主要是想把 node_modules 也打包进去。先是用 webpack,能打包成功,但是运行失败。后面又用 rollup,同样是打包成功,运行失败。可能是因为 nextjs 本身就包含了 webpack,而用打包工具来打包自己,估计 webpack 和 rollup 都没有想过会有这样的场景出现。于是放弃。

3

这个比较坑,所以重点说一下。

nextjs 提供了 assetPrefix 参数,但是这个参数基本没什么用。需要解决两个问题,一是打包目录要把 hash 带进去,把原来的 bundles/pages/xxx.js 目录结构改成 [hash]/xxx.js,这一步可以在打包脚本里处理,通过 BUILD_ID 和 build-stats.json 拿到 hash,直接上代码:

rm -r -f build
mkdir build

# move pages
buildId=$(cat _next/BUILD_ID)
mkdir build/${buildId}
mv _next/bundles/pages/* build/${buildId}
rm -r _next/bundles

# move app.js
appHash=$(cat _next/build-stats.json)
appHash=${appHash#*hash\":\"}
appHash=${appHash%\"*}
mv _next/app.js build/app.${appHash}.js

其中,_next 是 nextjs 的 distDir,build 是需要上传到 cdn 的目录。

接下来在 server.js 里重写 router,用了 express,参考 https://github.com/zeit/next.js/issues/257

const cdnPrefix = 'https://mycdn.com'

server.use('/_next/**/app.js', (req, res) => {
  const appHash = req.originalUrl.replace('/_next/', '').replace('/app.js', '')
  const newUrl = `${cdnPrefix}/build/app.${appHash}.js`
  res.redirect(newUrl)
})

server.use('/_next/**/page/**', (req, res) => {
  const buildHash = req.originalUrl.replace('/_next/', '').replace(/\/page\/.*/, '')
  const pageName = req.originalUrl.replace(/.*page\//, '') || 'index'
  const newUrl = `${cdnPrefix}/build/${buildHash}/${pageName}.js`
  res.redirect(newUrl)
})

4

static 目录下的图片 hash,这个问题也比较次要,暂时可以通过 githooks 来处理图片修改的问题,对于图片只允许增量提交。

.git/hooks/pre-commit

#!/bin/sh
STAGED_IMAGES=$(git diff --cached --name-only --diff-filter=M | grep -E ".(jpg|jpeg|png|gif)$")

if [[ $STAGED_IMAGES ]]; then
  echo $STAGED_IMAGES
  exit 1
fi

还有一些小坑,比如 process.env.NODE_ENV 的问题(如果有三种以上的环境),比如 scss 里面因不同环境插入不同 cdn 地址图片的问题,等等,就不列了。

生产项目:https://www.isspu.com

回归 express

express4-15

用 koa 踩了一些坑后,决定回归 express,等 koa 生态起来以后再用。

再看 express 最近的几次更新,好像今年突然有变勤快的趋势。

Release Change Log

4.15.0 – Release date: 2017-03-01
4.14.1 – Release date: 2017-01-28
4.14.0 – Release date: 2016-06-16

http://expressjs.com/en/changelog/4x.html

如今写本前端书真不容易

WechatIMG30

(图:《Node.js 硬实战》)

新书到手,啪啪啪翻了下,看到一段,说当时写这本书时 grunt 正流行,然后提到了 gulp。心想,如今写本技术书真心不容易,等你写出来的时候,已经过时了,尤其是前端书。

koa2后端项目打包成单个js文件

IMG_0998

(图:这两天爱上拍夜景)

之前发过一篇 node 后端项目文件打包,是用 webpack 把 express 项目打包成单个文件,坑相对少。

最近用 webpack 打包 koa2,踩了两个大坑。

第一坑:不支持 async

koa2 中间件支持三种写法

  • common function
  • async function
  • generatorFunction

可以用 common function 的写法,虽然用不了拉风的 async/await,但好处也有,省去了对 babel 的依赖。

第二坑:any-promise

这个库在打包的时候会报错,看了下它的 package.json,发现 devDependencies 依赖的库并没有 install。然后发现其实并不需要依赖 any-promise,直接用 node 6 及以上的版本就可以了。

编辑文件:

node_modules/koa-compose/index.js

注释掉开头的一行

const Promise = require(‘any-promise’)

填完这两个坑就好办了。

源码:https://github.com/taichenglu/koa-bundle

node 后端项目文件打包

IMG_1073

(图:五点不到就天黑了)

node 后端文件理论上不需要打包,但是用了 docker,发现每次创建的镜像都很大。这几天研究了下,使用 webpack,像打包前端代码一样打包后端代码,以便在创建 docker 镜像时过滤 node_modules,使镜像变小,加快 push 速度。

项目地址:https://github.com/taichenglu/docker-node-bundle

参考:https://segmentfault.com/a/1190000006023471

nvm auto use

WechatIMG30

(图:liza 提供的迷你下午茶)

nvm 有一个 nvm use 的命令,可以切换不同版本的 node,方便在不同项目中使用不同版本的 node,但是切换项目时经常会忘记打 use 命令,于是想有没有一个类似 nvm auto use 的东东,还确实是有的。

官方提供了 zsh 的解决方案(zsh 应该是 mac 程序员的标配了,还没安装的同学赶紧去 Install 吧)。

1、在项目根目录下创建一个 .nvmrc 文件,只要在这个文件里写一个数字就行,比如写个 6

2、vim ~/.zshrc

3、把官方提供的那段代码粘贴到 .zshrc 文件里,建议到 官方网页 去拷贝以下代码,以确保无误:

# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  if [ -n "$nvmrc_path" ]; then
    local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

    if [ "$nvmrc_node_version" != "N/A" ] && [ "$nvmrc_node_version" != "$node_version" ]; then
      nvm use 
    fi
  elif [ "$node_version" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc

4、重启命令终端,以后 cd 到不同目录时,nvm 就会自动查找目录下的 .nvmrc 文件,然后自动执行 nvm use.

第一个 node 应用

WechatIMG44

(图:阳光下)

前几天边学边做的第一个 node 应用。通过微信 JS-SDK 实现:

  • 分享给朋友
  • 分享到朋友圈

https://github.com/taichenglu/wechat-sdk-node