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