Next.js 笔记

NEXT 中文文档地址!

  1. next.js 只有服务端使用的包需要做单独处理,无需打包到项目中,可以使用@zeit/next-bundle-analyzer观察代码。
  2. Router.beforePopState() 截断Router操作的设置只有在客户端生效(需在componentDidMount中设置)且进入此函数中的方法只有Router栈中有值的时候才可以!
  3. next.js 中设置绝对路径的方法是在next.config.js中wepack方法中的config参数增加配置。
  4. next.js 中配置自定义接口可以使用自定义启动参数,创建 server.js 通过 node server.js 启动。
  5. next.js 支持IE11和各主流浏览器 IE11以内的IE版本不支持。
  6. Link 标签passHref属性可以强制给子元素传递href属性,有利于SEO优化。
  7. windows 不支持 NODE_ENV=development的设置方式 导入 cross-env 然后运行时在前面添加 cross-env 即可解决。
  8. webpack 配置自定义的时候覆盖配置需要继承本有的配置,否则会使 next 解析错误(analysis error)。
    module.exports = {
        // ... other next.js config
        return {
            webpack: config => {
                config.resolve.alias = {
                    ...(config.resolve.alias || {}),
                    // custom webpack aliases
                }
                return config
            }
        }
    }
  9. null-loader 加载器的一个用途是关闭依赖项导入的模块。 例如,你的项目依赖于导入你不需要的polyfill的ES6库,因这里删除它将导致不会丢失功能。 测试polyfill的路径,它将不包含在你的包中。
  10. next.js 引入antd @zeit/next-css babel-plugin-import 按需加载无法正确编译css文件需要在next.config.js中配置服务端渲染方可。
    const withCss = require('@zeit/next-css')
    
    module.exports = withCss({
        webpack: (config, { isServer }) => {
            if (isServer) {
                const antStyles = /antd\/.*?\/style\/css.*?/
                const origExternals = [...config.externals]
                config.externals = [
                    (context, request, callback) => {
                        if (request.match(antStyles)) return callback()
                        if (typeof origExternals[0] === 'function') {
                            origExternals[0](context, request, callback)
                        } else {
                            callback()
                        }
                    },
                    ...(typeof origExternals[0] === 'function' ? [] : origExternals),
                ]
    
                config.module.rules.unshift({
                    test: antStyles,
                    use: 'null-loader',
                })
            }
            return config
        },
    })
  11. next.js 引入@zeit/less需要将antd的按需加载style改为true。
  12. postCss/postCss-use 使用方法:
    module.exports = {
        plugins: [
            require('postcss-use')({
                // allow autoprefixer
                modules: [ 'autoprefixer' ]
            })
        ]
    }
  13. analysis && antd 3.x.x version icon 异步加载(next配置方案) && moment 语言包打包优化。
    moment 语言包使用 webpack.IgnorePlugin 会把所有语言过滤掉,所以需要使用 webpack.ContextReplacementPlugin 来指定打包筛选方案,然后单独引入所需moment语言包即可!
    const webpack = require('webpack')
    const withSass = require('@zeit/next-sass');
    const withBundleAnalyzer = require("@zeit/next-bundle-analyzer")
    module.exports = withBundleAnalyzer(withSass({
        analyzeServer: ["server", "both"].includes(process.env.BUNDLE_ANALYZE),
        analyzeBrowser: ["browser", "both"].includes(process.env.BUNDLE_ANALYZE),
        bundleAnalyzerConfig: {
            server: {
            analyzerMode: 'static',
            reportFilename: '../../bundles/server.html'
            },
            browser: {
            analyzerMode: 'static',
            reportFilename: '../bundles/client.html'
            }
        },
        webpack: (config, { dev }) => {
            config.module.rules.push(
                {
                    test: /\.(ttf|eot|svg|png|jpg|gif|ico)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
                    loader: 'file-loader',
                    options: {
                        name: '../../../[path][name].[ext]'
                    }
                }, {
                    test: /\.(css|scss)/,
                    loader: 'emit-file-loader',
                    options: {
                        name: 'dist/[path][name].[ext]'
                    }
                }, {
                    test: /\.css$/,
                    use: ['babel-loader', 'raw-loader', 'postcss-loader']
                }
                //, {
                //     test: /\.s(a|c)ss$/,
                //     use: ['babel-loader', 'raw-loader', 'postcss-loader',
                //         {
                //             loader: 'sass-loader',
                //             options: {
                //                 includePaths: ['styles', 'node_modules']
                //                     .map((d) => path.join(__dirname, d))
                //                     .map((g) => glob.sync(g))
                //                     .reduce((a, c) => a.concat(c), [])
                //             }
                //         }
                //     ]
                // }
            )
            !dev && config.module.rules.push({
                loader:'webpack-ant-icon-loader',
                enforce: 'pre',
                options:{
                    chunkName:'antd-icons'
                },
                include: [
                    require.resolve('@ant-design/icons/lib/dist.js')
                ]
            })
            !dev && config.plugins.push(
                // 阻止生成与正则表达式或过滤器函数匹配的模块import或require调用
                // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
                // 引入未知包的时候webpack会推断出directory的包,然后全部打包进入bundle,此条配置允许覆盖推断信息,更加精确的配置打包数据
                new webpack.ContextReplacementPlugin(
                    /moment[\\\/]locale$/,
                    /^\.\/(th)\.js$/
                )
                // 加到next/webpack.js配置中
                // new webpack.optimize.CommonsChunkPlugin({
                //     // name: 'icons',
                //     // filename: 'icons.js',
                //     minChunks: function (module, count) {
                //     if (dev || (module.resource && module.resource.includes('icons'))) {
                //         return false;
                //     }
                //     }
                // }),
            )
            return config
        },
        // exportPathMap: function (defaultPathMap) {
        //     return {
        //         '/': { page: '/' },
        //     }
        // }
    }))
  14. 针对低版本next使用的webpack3配置中使用webpack-icons-loader需要单独配置以及处理export之后的文件索引,方案为:
    var fs = require('fs')
    var path = require('path')
    
    function editWebpack (srcPath) {
        let prefix = path.extname(srcPath)
        // 过滤除js和html的文件
        if (prefix === '.js') {
            const data = fs.readFileSync(srcPath, 'utf8');
            let line = data.split('\n')
            let len = line.length
            let newLines = ''
            let isEdit = false
    
            for (let i = 0; i < len; i++) {
                if (i > 347 && i < 350) {
                    let isFind = ~line[i].indexOf('(dev)')
                    !isEdit && (isEdit = isFind)
                    line[i] = isFind ? '                  if (dev || (module.resource && module.resource.includes(\'icons\') && count >= 0)) {' : line[i]
                }
    
                newLines += line[i] + (i !== len - 1 ? '\n' : '')
            }
            
            fs.writeFileSync(srcPath, newLines, 'utf8');
            isEdit && console.log('webpack update success:' + srcPath + '\n')
        }
    }
    
    function editIcons (srcPath, tarPath) {
        let prefix = path.extname(srcPath)
        // 过滤除js和html的文件
        if (prefix === '.js') {
            const data = fs.readFileSync(srcPath, 'utf8');
    
            fs.writeFileSync(tarPath, data, 'utf8')
            console.log('@ant-design update success:' + tarPath + '\n')
        }
    }
    
    editWebpack('./node_modules/next/dist/server/build/webpack.js')
    editIcons('./static/font/dist.js', './node_modules/@ant-design/icons/lib/dist.js')
    var fs = require('fs')
    var path = require('path')
    
    function findFolder (srcDir, tarDir) {
        // 读取当前路径下的所有目录和文件,返回字符串数组
        fs.readdir(srcDir, function (err, files) {
            files.forEach(function (file) {
                if (!~file.indexOf('antd-icons')) return
                var srcPath = path.join(srcDir, file)
                var tarPath = path.join(tarDir, file)
    
                fs.stat(srcPath, function (err, stats) {
                    !stats.isDirectory() && copyFile(srcPath, tarPath)
                })
            })
    
        })
    }
    
    function copyFile(srcPath, tarPath) {
        // 创建字节读取流
        var rs = fs.createReadStream(srcPath)
        rs.on('error', function (err) {
            if (err) {
                console.log('read error', srcPath)
            }
        })
    
        // 创建字节写入流
        var ws = fs.createWriteStream(tarPath)
        ws.on('error', function (err) {
            if (err) {
                console.log('write error', tarPath)
            }
        })
        ws.on('close', function (ex) {
        })
    
        rs.pipe(ws)
        console.log('ant-icons move success:' + srcPath + '\n')
    }
    
    findFolder('./.next/', './out/_next/webpack/')

     

posted @ 2019-06-07 10:48  universe-cosmo  阅读(1582)  评论(0编辑  收藏  举报