肖兴中 發表於 2019-6-7 10:48:00

Next.js 笔记

<div class="main-body">
<p>NEXT 中文文档地址!</p>
<ol>
<li>next.js 只有服务端使用的包需要做单独处理,无需打包到项目中,可以使用@zeit/next-bundle-analyzer观察代码。</li>
<li>Router.beforePopState() 截断Router操作的设置只有在客户端生效(需在componentDidMount中设置)且进入此函数中的方法只有Router栈中有值的时候才可以!</li>
<li>next.js 中设置绝对路径的方法是在next.config.js中wepack方法中的config参数增加配置。</li>
<li>next.js 中配置自定义接口可以使用自定义启动参数,创建 server.js 通过 node server.js 启动。</li>
<li>next.js 支持IE11和各主流浏览器 IE11以内的IE版本不支持。</li>
<li>Link 标签passHref属性可以强制给子元素传递href属性,有利于SEO优化。</li>
<li>windows 不支持 NODE_ENV=development的设置方式 导入 cross-env 然后运行时在前面添加 cross-env 即可解决。</li>
<li>webpack 配置自定义的时候覆盖配置需要继承本有的配置,否则会使 next 解析错误(analysis error)。
<div class="cnblogs_code">
<pre>module.exports =<span style="color: rgba(0, 0, 0, 1)"> {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ... other next.js config</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
      webpack: config </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
            config.resolve.alias </span>=<span style="color: rgba(0, 0, 0, 1)"> {
                ...(config.resolve.alias </span>||<span style="color: rgba(0, 0, 0, 1)"> {}),
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> custom webpack aliases</span>
<span style="color: rgba(0, 0, 0, 1)">            }
            </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> config
      }
    }
}</span></pre>
</div>
</li>
<li>null-loader 加载器的一个用途是关闭依赖项导入的模块。 例如,你的项目依赖于导入你不需要的polyfill的ES6库,因这里删除它将导致不会丢失功能。 测试polyfill的路径,它将不包含在你的包中。</li>
<li>next.js 引入antd @zeit/next-css babel-plugin-import 按需加载无法正确编译css文件需要在next.config.js中配置服务端渲染方可。
<div class="cnblogs_code">
<pre>const withCss = require('@zeit/next-css'<span style="color: rgba(0, 0, 0, 1)">)

module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> withCss({
    webpack: (config, { isServer }) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isServer) {
            const antStyles </span>= /antd\/.*?\/style\/css.*?/<span style="color: rgba(0, 0, 0, 1)">
            const origExternals </span>=<span style="color: rgba(0, 0, 0, 1)"> [...config.externals]
            config.externals </span>=<span style="color: rgba(0, 0, 0, 1)"> [
                (context, request, callback) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (request.match(antStyles)) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> callback()
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">typeof</span> origExternals === 'function'<span style="color: rgba(0, 0, 0, 1)">) {
                        origExternals[</span>0<span style="color: rgba(0, 0, 0, 1)">](context, request, callback)
                  } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                        callback()
                  }
                },
                ...(</span><span style="color: rgba(0, 0, 255, 1)">typeof</span> origExternals === 'function' ?<span style="color: rgba(0, 0, 0, 1)"> [] : origExternals),
            ]

            config.module.rules.unshift({
                test: antStyles,
                use: </span>'null-loader'<span style="color: rgba(0, 0, 0, 1)">,
            })
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> config
    },
})</span></pre>
</div>
</li>
<li>next.js 引入@zeit/less需要将antd的按需加载style改为true。</li>
<li>postCss/postCss-use 使用方法:
<div class="cnblogs_code">
<pre>module.exports =<span style="color: rgba(0, 0, 0, 1)"> {
    plugins: [
      require(</span>'postcss-use'<span style="color: rgba(0, 0, 0, 1)">)({
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> allow autoprefixer</span>
            modules: [ 'autoprefixer'<span style="color: rgba(0, 0, 0, 1)"> ]
      })
    ]
}</span></pre>
</div>
</li>
<li>analysis &amp;&amp; antd 3.x.x version icon 异步加载(next配置方案) &amp;&amp; moment 语言包打包优化。<br>
moment 语言包使用 webpack.IgnorePlugin 会把所有语言过滤掉,所以需要使用 webpack.ContextReplacementPlugin 来指定打包筛选方案,然后单独引入所需moment语言包即可!
<div class="cnblogs_code">
<pre>const webpack = require('webpack'<span style="color: rgba(0, 0, 0, 1)">)
const withSass </span>= require('@zeit/next-sass'<span style="color: rgba(0, 0, 0, 1)">);
const withBundleAnalyzer </span>= require("@zeit/next-bundle-analyzer"<span style="color: rgba(0, 0, 0, 1)">)
module.exports </span>=<span style="color: rgba(0, 0, 0, 1)"> withBundleAnalyzer(withSass({
    analyzeServer: [</span>"server", "both"<span style="color: rgba(0, 0, 0, 1)">].includes(process.env.BUNDLE_ANALYZE),
    analyzeBrowser: [</span>"browser", "both"<span style="color: rgba(0, 0, 0, 1)">].includes(process.env.BUNDLE_ANALYZE),
    bundleAnalyzerConfig: {
      server: {
      analyzerMode: </span>'static'<span style="color: rgba(0, 0, 0, 1)">,
      reportFilename: </span>'../../bundles/server.html'<span style="color: rgba(0, 0, 0, 1)">
      },
      browser: {
      analyzerMode: </span>'static'<span style="color: rgba(0, 0, 0, 1)">,
      reportFilename: </span>'../bundles/client.html'<span style="color: rgba(0, 0, 0, 1)">
      }
    },
    webpack: (config, { dev }) </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      config.module.rules.push(
            {
                test: </span>/\.(ttf|eot|svg|png|jpg|gif|ico)(\?v=\.\.)?$/<span style="color: rgba(0, 0, 0, 1)">,
                loader: </span>'file-loader'<span style="color: rgba(0, 0, 0, 1)">,
                options: {
                  name: </span>'../../../.'<span style="color: rgba(0, 0, 0, 1)">
                }
            }, {
                test: </span>/\.(css|scss)/<span style="color: rgba(0, 0, 0, 1)">,
                loader: </span>'emit-file-loader'<span style="color: rgba(0, 0, 0, 1)">,
                options: {
                  name: </span>'dist/.'<span style="color: rgba(0, 0, 0, 1)">
                }
            }, {
                test: </span>/\.css$/<span style="color: rgba(0, 0, 0, 1)">,
                use: [</span>'babel-loader', 'raw-loader', 'postcss-loader'<span style="color: rgba(0, 0, 0, 1)">]
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">, {</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   test: /\.s(a|c)ss$/,</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   use: ['babel-loader', 'raw-loader', 'postcss-loader',</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">         {</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">             loader: 'sass-loader',</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">             options: {</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">               includePaths: ['styles', 'node_modules']</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">                     .map((d) =&gt; path.join(__dirname, d))</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">                     .map((g) =&gt; glob.sync(g))</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">                     .reduce((a, c) =&gt; a.concat(c), [])</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">             }</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">         }</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   ]</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> }</span>
<span style="color: rgba(0, 0, 0, 1)">      )
      </span>!dev &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> config.module.rules.push({
            loader:</span>'webpack-ant-icon-loader'<span style="color: rgba(0, 0, 0, 1)">,
            enforce: </span>'pre'<span style="color: rgba(0, 0, 0, 1)">,
            options:{
                chunkName:</span>'antd-icons'<span style="color: rgba(0, 0, 0, 1)">
            },
            include: [
                require.resolve(</span>'@ant-design/icons/lib/dist.js'<span style="color: rgba(0, 0, 0, 1)">)
            ]
      })
      </span>!dev &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> config.plugins.push(
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 阻止生成与正则表达式或过滤器函数匹配的模块import或require调用</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引入未知包的时候webpack会推断出directory的包,然后全部打包进入bundle,此条配置允许覆盖推断信息,更加精确的配置打包数据</span>
            <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> webpack.ContextReplacementPlugin(
                </span>/moment[\\\/]locale$/<span style="color: rgba(0, 0, 0, 1)">,
                </span>/^\.\/(th)\.js$/<span style="color: rgba(0, 0, 0, 1)">
            )
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加到next/webpack.js配置中</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> new webpack.optimize.CommonsChunkPlugin({</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   // name: 'icons',</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   // filename: 'icons.js',</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   minChunks: function (module, count) {</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   if (dev || (module.resource &amp;&amp; module.resource.includes('icons'))) {</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">         return false;</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   }</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   }</span>
            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> }),</span>
<span style="color: rgba(0, 0, 0, 1)">      )
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> config
    },
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> exportPathMap: function (defaultPathMap) {</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   return {</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">         '/': { page: '/' },</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">   }</span>
    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> }</span>
}))</pre>
</div>
</li>
<li>针对低版本next使用的webpack3配置中使用webpack-icons-loader需要单独配置以及处理export之后的文件索引,方案为:
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> fs = require('fs'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">var</span> path = require('path'<span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> editWebpack (srcPath) {
    let prefix </span>=<span style="color: rgba(0, 0, 0, 1)"> path.extname(srcPath)
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过滤除js和html的文件</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (prefix === '.js'<span style="color: rgba(0, 0, 0, 1)">) {
      const data </span>= fs.readFileSync(srcPath, 'utf8'<span style="color: rgba(0, 0, 0, 1)">);
      let line </span>= data.split('\n'<span style="color: rgba(0, 0, 0, 1)">)
      let len </span>=<span style="color: rgba(0, 0, 0, 1)"> line.length
      let newLines </span>= ''<span style="color: rgba(0, 0, 0, 1)">
      let isEdit </span>= <span style="color: rgba(0, 0, 255, 1)">false</span>

      <span style="color: rgba(0, 0, 255, 1)">for</span> (let i = 0; i &lt; len; i++<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (i &gt; 347 &amp;&amp; i &lt; 350<span style="color: rgba(0, 0, 0, 1)">) {
                let isFind </span>= ~line.indexOf('(dev)'<span style="color: rgba(0, 0, 0, 1)">)
                </span>!isEdit &amp;&amp; (isEdit =<span style="color: rgba(0, 0, 0, 1)"> isFind)
                line </span>= isFind ? '                  if (dev || (module.resource &amp;&amp; module.resource.includes(\'icons\') &amp;&amp; count &gt;= 0)) {'<span style="color: rgba(0, 0, 0, 1)"> : line
            }

            newLines </span>+= line + (i !== len - 1 ? '\n' : ''<span style="color: rgba(0, 0, 0, 1)">)
      }
      
      fs.writeFileSync(srcPath, newLines, </span>'utf8'<span style="color: rgba(0, 0, 0, 1)">);
      isEdit </span>&amp;&amp; console.log('webpack update success:' + srcPath + '\n'<span style="color: rgba(0, 0, 0, 1)">)
    }
}

</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> editIcons (srcPath, tarPath) {
    let prefix </span>=<span style="color: rgba(0, 0, 0, 1)"> path.extname(srcPath)
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 过滤除js和html的文件</span>
    <span style="color: rgba(0, 0, 255, 1)">if</span> (prefix === '.js'<span style="color: rgba(0, 0, 0, 1)">) {
      const data </span>= fs.readFileSync(srcPath, 'utf8'<span style="color: rgba(0, 0, 0, 1)">);

      fs.writeFileSync(tarPath, data, </span>'utf8'<span style="color: rgba(0, 0, 0, 1)">)
      console.log(</span>'@ant-design update success:' + tarPath + '\n'<span style="color: rgba(0, 0, 0, 1)">)
    }
}

editWebpack(</span>'./node_modules/next/dist/server/build/webpack.js'<span style="color: rgba(0, 0, 0, 1)">)
editIcons(</span>'./static/font/dist.js', './node_modules/@ant-design/icons/lib/dist.js')</pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> fs = require('fs'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">var</span> path = require('path'<span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> findFolder (srcDir, tarDir) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 读取当前路径下的所有目录和文件,返回字符串数组</span>
    fs.readdir(srcDir, <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (err, files) {
      files.forEach(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (file) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!~file.indexOf('antd-icons')) <span style="color: rgba(0, 0, 255, 1)">return</span>
            <span style="color: rgba(0, 0, 255, 1)">var</span> srcPath =<span style="color: rgba(0, 0, 0, 1)"> path.join(srcDir, file)
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> tarPath =<span style="color: rgba(0, 0, 0, 1)"> path.join(tarDir, file)

            fs.stat(srcPath, </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (err, stats) {
                </span>!stats.isDirectory() &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> copyFile(srcPath, tarPath)
            })
      })

    })
}

</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> copyFile(srcPath, tarPath) {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建字节读取流</span>
    <span style="color: rgba(0, 0, 255, 1)">var</span> rs =<span style="color: rgba(0, 0, 0, 1)"> fs.createReadStream(srcPath)
    rs.on(</span>'error', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
            console.log(</span>'read error'<span style="color: rgba(0, 0, 0, 1)">, srcPath)
      }
    })

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建字节写入流</span>
    <span style="color: rgba(0, 0, 255, 1)">var</span> ws =<span style="color: rgba(0, 0, 0, 1)"> fs.createWriteStream(tarPath)
    ws.on(</span>'error', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
            console.log(</span>'write error'<span style="color: rgba(0, 0, 0, 1)">, tarPath)
      }
    })
    ws.on(</span>'close', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (ex) {
    })

    rs.pipe(ws)
    console.log(</span>'ant-icons move success:' + srcPath + '\n'<span style="color: rgba(0, 0, 0, 1)">)
}

findFolder(</span>'./.next/', './out/_next/webpack/')</pre>
</div>
<p>&nbsp;</p>
</li>
</ol></div><br><br>
来源:https://www.cnblogs.com/universe-cosmo/p/10987778.html
頁: [1]
查看完整版本: Next.js 笔记