Next.js实战
文章目录
Next.js是目前用于实现 React 服务端渲染框架中的比较流行的一个,得力于ZEIT的维护,使得相对于其它的一些框架,不论是在文档还是配套上面,它都比较齐全。
官方就提供了learnnextjs这样的交互式入门教程,这里就不多说了(结合文档效果更好)。
既然是实战,这里就说点自己遇到的问题及解决方案,下面将问题总的划分为几个分类:
JS 方面的坑
使用jsx作为文件后缀?
一开始笔者习惯性的使用jsx作为文件后缀,发现控制台中老是报错,说是模块没有找到,这种一看就是配置问题,需要修改next.config.js中 webpack 的配置,增加extensions的jsx还有对应的babel-loader的配置,结果发现完全不起作用,看来是 next.js 中对于相关文件做了特殊的处理,目前来看只能使用*.js作为文件后缀了。
官方目前的回复也是这样,暂时就支持*.js作为后缀,具体可以看一下这个issue
JS 中读取process.env.*返回undefined?
如果直接用node执行*.js文件,那么cross-env就比较合适,这个包帮我们处理的跨平台时env定义的问题,但是next.js是依赖于构建工具webpack的,换句话说,如果直接在package.json的scripts中使用cross-env是无法直接影响webpack的处理结果的,还需要用到webpack.DefinePlugin这个插件来做一次定义,next.js提供了一个简单的例子,核心代码如下:
| |
另外,这只是其中的一个解决方法,next.js还提供了一个基于Babel和dotenv的例子,原理就是在 Babel 处理阶段就将代码中的process.env.*替换处理。
使用babel处理node_modules中部分 JS 的方法?
为了兼容 Android4.3,就必须要用 babel 结合相关的工具对 ES6 做兼容性处理,但是,默认的next.config.js中关于jsx的处理一般都会设置exclude过滤掉node_modules,就像这样的配置:
| |
next.js的 issues 中有不少关于这个的讨论,目前实践下来,最简单的就是直接修改exclude属性即可:
| |
当然,babel 还需要结合.babelrc和.browserslistrc这些配置项及babel-plugin-transform-runtime这样的工具,如果需要了解更多,可以参考 Babel 笔记 这篇文章。
Static 静态资源方面的坑
官网教程中并没有全面的介绍如何控制好静态资源的加载及维护,下面就说说一些常见的问题。
如何引入图片、字体等静态资源?
webpack 及配套的*-loader,使得我们可以很方便的在 JS 文件中通过import载入各种静态资源,不过 next.js 基础中并未对图片、字体等文件做特殊配置,所以需要我们手动在next.config.js中增加 webpack 的相关配置:
| |
如何引用全局静态资源?
官网的推荐是在根目录的static文件夹中放入即可,后续不论是在 JS 还是 CSS 文件中,只需要写绝对路径/static/{path_to_file}即可,next.js 帮助做了一些类似于路由映射的处理,很遗憾,官方并未给出 cache 的方案,目前来看有 2 中思路
1. 基于 URL 中param的 cache 方案
| |
2. 基于 URL 中path结合脚本迁移文件路*(暂时是个思路,未具体实现)*
| |
文件迁移脚本
jq是一个轻量级的命令行 JSON 处理工具
| |
CSS 方面的坑
官方提供了很多 CSS 的示例,但是个人觉得这个是踩坑最多的地方
实现CSS Modules?
得益于css-loader,如果单单是做客户端渲染,只需要在 webpack 的配置中启用modules配置即可,从而简简单单的实现BEM,但是 Next.js 官方并不支持该方案,具体可以参考这个issue,虽然大家也都集思广益,造出了各种方案,但是具体实施起来效果都不怎么理想,反倒是官方推荐的styled-jsx方案,结合postcss之后,成了不错的选择。
with-styled-jsx-plugins这个例子已经实现了基础的配置,你只需要增加postcss.config.js扩展一下即可:
| |
styled-jsx与 babel 的冲突?
之前在babel的生产环境发布前,会利用一些plugin优化 react 的产出代码,其中最常用的就是transform-react-remove-prop-types、transform-react-constant-elements、transform-react-inline-elements,这个时候 styled-jsx对于<style jsx>{***}</style>中的处理就会与**transform-react-constant-elements、transform-react-inline-elements**冲突了,导致无法正常处理scope及optimized的功能,这里建议直接将transform-react-constant-elements和transform-react-inline-elements去除即可。
cssnano处理后@font-face内容缺失?
一般现在都会在上生产环境前使用 cssnano 对 CSS 文件做一次压缩优化,不过现在碰到一个问题,在处理后,@font-face的内容缺失了,cssnano 的 issue 中有人提供了解决方式:禁用其对@font-face的优化即可。
| |
首次渲染pages/_document.js,全局未能生效?
next.js 推荐使用styled-jsx处理 css,所以在_document.js中想当然的使用了下面的写法:
| |
这样就直接导致了一个问题,在第一次访问服务的时候,发现mainStyles中的内容并未被加载并执行,next.js 的issues 中有人也已经反映过这个问题并且给出了解决方案,简单来说就是直接使用<style>加载即可,不要使用<style jsx global>。
文章作者 tony
上次更新 2017-11-01