详解React 服务端渲染方案完美的解决方案(5)
静态资源处理方案
在客户端中,我们使用了大量的ES6/7语法,jsx语法,css资源,图片资源,最终通过webpack配合各种loader打包成一个文件最后运行在浏览器环境中。但是在服务端,不支持import、jsx这种语法,并且无法识别对css、image资源后缀的模块引用,那么要怎么处理这些静态资源呢?我们需要借助相关的工具、插件来使得Node.js解析器能够加载并执行这类代码,下面分别为开发环境和产品环境配置两套不同的解决方案。
开发环境
首先引入babel-polyfill这个库来提供regenerator运行时和core-js来模拟全功能ES6环境。
引入babel-register,这是一个require钩子,会自动对require命令所加载的js文件进行实时转码,需要注意的是,这个库只适用于开发环境。
引入css-modules-require-hook,同样是钩子,只针对样式文件,由于我们采用的是CSS Modules方案,并且使用SASS来书写代码,所以需要node-sass这个前置编译器来识别扩展名为.scss的文件,当然你也可以采用LESS的方式,通过这个钩子,自动提取className哈希字符注入到服务端的React组件中。
引入asset-require-hook,来识别图片资源,对小于8K的图片转换成base64字符串,大于8k的图片转换成路径引用。
// Provide custom regenerator runtime and core-js require('babel-polyfill') // Javascript required hook require('babel-register')({presets: ['es2015', 'react', 'stage-0']}) // Css required hook require('css-modules-require-hook')({ extensions: ['.scss'], preprocessCss: (data, filename) => require('node-sass').renderSync({ data, file: filename }).css, camelCase: true, generateScopedName: '[name]__[local]__[hash:base64:8]' }) // Image required hook require('asset-require-hook')({ extensions: ['jpg', 'png', 'gif', 'webp'], limit: 8000 })
产品环境
对于产品环境,我们的做法是使用webpack分别对客户端和服务端代码进行打包。客户端代码打包这里不多说,对于服务端代码,需要指定运行环境为node,并且提供polyfill,设置__filename和__dirname为true,由于是采用CSS Modules,服务端只需获取className,而无需加载样式代码,所以要使用css-loader/locals替代css-loader加载样式文件
// webpack.config.js { target: 'node', node: { __filename: true, __dirname: true }, module: { loaders: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel', query: {presets: ['es2015', 'react', 'stage-0']} }, { test: /\.scss$/, loaders: [ 'css/locals?modules&camelCase&importLoaders=1&localIdentName=[hash:base64:8]', 'sass' ] }, { test: /\.(jpg|png|gif|webp)$/, loader: 'url?limit=8000' }] } }
内容版权声明:除非注明,否则皆为本站原创文章。