脚本宝典收集整理的这篇文章主要介绍了

react 应用多入口 配置 && 实践总结

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <h1 id="articleHeader0">背景</h1> <p>还是之前的那个项目,做完国际化没多久,还没来得及划水, 又有新的活了 -- 移动端的兼容。 考虑到后期的复杂度, 需要做两套资源。 具体的目标是:<code>同一个URL,PC打开就显示PC的那一套, M端打开就显示Mobile的页面</code>。 create-react-app 脚手架本身不支持多入口, 需要改造,今天下午研究了一下,改造了一波, 基本达到了预期, 在这里简单把经验总结分享下。</p> <h1 id="articleHeader1">先睹为快</h1> <p>Mobile:</p> <p><span class="img-wrap"><img data-src="/img/bVbh6dd?w=1972&amp;h=1630" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>PC:</p> <p><span class="img-wrap"><img data-src="/img/bVbh6d7?w=1740&amp;h=1996" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p><span class="img-wrap"><img data-src="/img/bVbh6f8?w=412&amp;h=450" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>输出之后的文件, 相比之前的index.html, 多了一个额外的mobile.html.</p> <p>最终的源代码目录:</p> <p><span class="img-wrap"><img data-src="/img/bVbh6hM?w=458&amp;h=1498" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>具体的改造步骤如下:</p> <h1 id="articleHeader2">Steps</h1> <h2 id="articleHeader3">step1: Eject</h2> <p>在下之前图方便, 直接用了<code>create-react-app</code>, 现在需要更改配置, 需要弹出默认配置:</p> <p>在终端执行:<code>yarn eject</code>.</p> <h2 id="articleHeader4">step2: 修改webpack config</h2> <p>原本的 webpack.config.dev.js:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="entry: [ require.resolve('react-dev-utils/webpackHotDevClient'), require.resolve('./polyfills'), require.resolve('react-error-overlay'), paths.appIndexJs, ], output: { path: paths.appBuild, pathinfo: true, filename: 'static/js/bundle.js', chunkFilename: 'static/js/[name].chunk.js', publicPath: publicPath, devtoolModuleFilenameTemplate: info =><br /> path.resolve(info.absoluteResourcePath),<br /> },<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs lua"><code>entry: [ <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'react-dev-utils/webpackHotDevClient'</span>), <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'./polyfills'</span>), <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'react-error-overlay'</span>), paths.appIndexJs, ], <span class="hljs-built_in">output</span>: { <span class="hljs-built_in">path</span>: paths.appBuild, pathinfo: <span class="hljs-literal">true</span>, filename: <span class="hljs-string">'static/js/bundle.js'</span>, chunkFilename: <span class="hljs-string">'static/js/[name].chunk.js'</span>, publicPath: publicPath, devtoolModuleFilename<a href="http://www.js-code.com/tag/template" title="浏览关于“Template”的文章" target="_blank" class="tag_link">Template</a>: info =&gt; <span class="hljs-built_in">path</span>.resolve(info.absoluteResourcePath), }, </code></pre> <p>需要修改为:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" entry: { index: [ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), paths.appIndexJs, ], mobile: [ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), paths.appSrc + &quot;/mobile/index.js&quot;, ] }, output: { pathinfo: true, filename: 'static/js/[name].bundle.js', chunkFilename: 'static/js/[name].chunk.js', publicPath: publicPath, devtoolModuleFilenameTemplate: info =><br /> path.resolve(info.absoluteResourcePath).replace(/\/g, '/'),<br /> },<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs css"><code> <span class="hljs-selector-tag">entry</span>: { <span class="hljs-attribute">index</span>: [ require.<span class="hljs-built_in">resolve</span>(<span class="hljs-string">'./polyfills'</span>), require.<span class="hljs-built_in">resolve</span>(<span class="hljs-string">'react-dev-utils/webpackHotDevClient'</span>), paths.appIndexJs, ], mobile: [ require.<span class="hljs-built_in">resolve</span>(<span class="hljs-string">'./polyfills'</span>), require.<span class="hljs-built_in">resolve</span>(<span class="hljs-string">'react-dev-utils/webpackHotDevClient'</span>), paths.appSrc + <span class="hljs-string">"/mobile/index.js"</span>, ] }, <span class="hljs-selector-tag">output</span>: { <span class="hljs-attribute">pathinfo</span>: true, filename: <span class="hljs-string">'static/js/[name].bundle.js'</span>, chunkFilename: <span class="hljs-string">'static/js/[name].chunk.js'</span>, publicPath: publicPath, devtoolModuleFilenameTemplate: info =&gt; path.<span class="hljs-built_in">resolve</span>(info.absoluteResourcePath).<span class="hljs-built_in">replace</span>(/\/g, <span class="hljs-string">'/'</span>), }, </code></pre> <p>可能需要注意的几点:</p> <ul> <li>entry从原来的<a href="http://www.js-code.com/tag/%e6%95%b0%e7%bb%84" title="数组" target="_blank">数组</a>扩展为对象,每个key代表一个入口。</li> <li>output中的filename要区分输出名,可增加[name]变量,这样会根据entry分别编译出每个entry的js文件。</li> </ul> <p>这样你就可以在<code>src</code> 目录下新起一个民目录开发新的SPA:</p> <p><span class="img-wrap"><img data-src="/img/bVbh6ig?w=362&amp;h=706" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <h2 id="articleHeader5">step3: 生成多个html入口文件</h2> <p>Webpack配置多入口后,只是编译出多个入口的Js,入口的<a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a>文件也需要配置, 可以用HtmlWebpackPlugin来生成。</p> <p><code>webpack.config.dev.js</code> 原配置:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" // Generates an `index.html` file with the <script> injected.<br /> new HtmlWebpackPlugin({<br /> inject: true,<br /> chunks: [&quot;index&quot;],<br /> template: paths.appHtml,<br /> }),<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs cpp"><code> <span class="hljs-comment">// Generates an `index.html` file with the &lt;script&gt; injected.</span> <span class="hljs-keyword">new</span> HtmlWebpackPlugin({ inject: <span class="hljs-literal">true</span>, chunks: [<span class="hljs-string">"index"</span>], <span class="hljs-keyword">template</span>: paths.appHtml, }), </code></pre> <p>需要加多一个配置, 改成:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text=" // Generates an `index.html` file with the <script> injected.<br /> new HtmlWebpackPlugin({<br /> inject: true,<br /> chunks: [&quot;index&quot;],<br /> template: paths.appHtml,<br /> }),<br /> new HtmlWebpackPlugin({<br /> inject: true,<br /> chunks: [&quot;mobile&quot;],<br /> template: paths.appHtml,<br /> filename: 'mobile.html',<br /> }),<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code> <span class="hljs-comment">// Generates an `index.html` file with the &lt;script&gt; injected.</span> <span class="hljs-keyword">new</span> <span class="hljs-type">HtmlWebpackPlugin</span>({ inject: <span class="hljs-literal">true</span>, chunks: [<span class="hljs-string">"index"</span>], template: paths.appHtml, }), <span class="hljs-keyword">new</span> <span class="hljs-type">HtmlWebpackPlugin</span>({ inject: <span class="hljs-literal">true</span>, chunks: [<span class="hljs-string">"mobile"</span>], template: paths.appHtml, filename: <span class="hljs-symbol">'mobile</span>.html', }), </code></pre> <ul> <li>每调一次HtmlWebpackPlugin生成一次<a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a>页面,这里有两个,所以就会多增加一个mobile.html节点。</li> <li>chunks: 指明哪些webpack入口的js会被注入到这个<a href="http://www.js-code.com/tag/html" title="浏览关于“HTML”的文章" target="_blank" class="tag_link">HTML</a>页面。如果不配置,则将所有entry的JS文件都注入HTML。</li> <li>filename: 指明生成的HTML路径,如果不配置就是dist/index.html。mobile配置了新的filename,避免与第一个入口相互覆盖。</li> <li>template: 指定模版, 我这里因为用的这两个模版都一样, 所以就指定的同一个appHtml, 如有特殊需求, 就新建一个html 文件, 在template字段里引用即可。</li> </ul> <h2 id="articleHeader6">Step4: 配置webpack Dev Server</h2> <p>上述配置做完后,理论就可以打包出多入口的版本;但使用npm start启动后,发现无论输入/index.html还是/mobile.html,好像都是和原来/index.html显示一样的内容。</p> <p>甚至输入显然不存在的/xxxx.html,也显示为/index.html的内容。</p> <p>这种现象,初步判断是HTTP服务器把所有请求重定向到了/index.html。</p> <p>对于单页应用,这种做法是没有问题的(本来就一个页面), 但我们新增的/mobile.html就可以访问到了。</p> <p>参考官方文档 The historyApiFallback option,发现是webpack dev server的问题,还要额外做一些配置,需修改webpackDevServer.config.js:</p> <p>原配置:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="historyApiFallback: { // Paths with dots should still use the history fallback. // See https://github.com/facebookincubator/create-react-app/issues/387. disableDotRule: true, }," title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs groovy"><code><span class="hljs-string">historyApiFallback:</span> { <span class="hljs-comment">// Paths with dots should still use the history fallback.</span> <span class="hljs-comment">// See https://github.com/facebookincubator/create-react-app/issues/387.</span> <span class="hljs-symbol"> disableDotRule:</span> <span class="hljs-literal">true</span>, },</code></pre> <p>修改为:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="historyApiFallback: { // Paths with dots should still use the history fallback. // See https://github.com/facebookincubator/create-react-app/issues/387. disableDotRule: true, // 指明哪些路径映射到哪个html rewrites: [ { from: /^/mobile.html/, to: '/dist/mobile.html' }, ] }," title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code>historyApiFallback: { <span class="hljs-comment">// Paths with dots should still use the history fallback.</span> <span class="hljs-comment">// See https://github.com/facebookincubator/create-react-app/issues/387.</span> disableDotRule: <span class="hljs-literal">true</span>, <span class="hljs-comment">// 指明哪些路径映射到哪个html</span> rewrites: [ { <span class="hljs-keyword">from</span>: <span class="hljs-regexp">/^/mobile.html/</span>, to: <span class="hljs-string">'/dist/mobile.html'</span> }, ] },</code></pre> <p>增加的rewrites节点,特别对/admin.html这个URL重定向为/dist/mobile.html页面(也就是HtmlWebpackPlugin输出的HTML文件路径),这样/mobile.html就可以正常访问了。</p> <p>至此,dev环境的多入口问题就解决了。</p> <h2 id="articleHeader7">step5: Prod 环境配置</h2> <p>prod环境,比dev环境更简单。由于不存在webpack Dev Server,直接在config/webpack.config.prod.js同理做2和3步骤即可。</p> <p>这时候你就可以通过手动修改URl 来访问了:</p> <p><span class="img-wrap"><img data-src="/img/bVbh6kk?w=1682&amp;h=1322" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p><span class="img-wrap"><img data-src="/img/bVbh6j8?w=1392&amp;h=1468" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <h1 id="articleHeader8">路由相关</h1> <p>到这, 已经可以手动修改URL 来访问pc 和 mobile的页面了。 还有一个问题没有解决:</p> <p>URL最后肯定是不能给你手动改来改去的, 需要根据设备的情况自己判断, 这里有两个思路:</p> <p>1: 配置 Nginx 的路径的时候, 加多一个alias 的映射。<br />2: 前端根据UA自行配置。</p> <p>为了快速出效果, 简单搞了一下, 具体代码如下:</p> <p><span class="img-wrap"><img data-src="/img/bVbh6kE?w=2022&amp;h=1698" src="https://cdn.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="clipboard.png" title="clipboard.png" style="cursor: pointer;"></span></p> <p>这样, 不用手动修改URL 也能根据UA自动显示不同的页面了, 具体的效果图在文章开头的<code>先睹为快</code>中。</p> <h1 id="articleHeader9">其他</h1> <p>上面的路由就为了简单的出个效果, 比较粗暴, 仅供参考。</p> <h1 id="articleHeader10">结语</h1> <p>以上就是全部的细节了, 达到了预期的效果, 但是也有很大优化空间。 等后面一波需求做完了, 再来做补充吧。:P</p> <p>End。</p> <p>参考资料:</p> <p><a href="https://medium.com/a-beginners-guide-for-webpack-2/index-html-using-html-webpack-plugin-85eabdb73474" rel="nofollow noreferrer" target="_blank">https://medium.com/a-beginner...</a></p> <p><a href="http://imshuai.com/create-react-app-multiple-entry-points/" rel="nofollow noreferrer" target="_blank">http://imshuai.com/create-rea...</a></p> <p></code></p>

总结

以上是脚本宝典为你收集整理的

react 应用多入口 配置 && 实践总结

全部内容,希望文章能够帮你解决

react 应用多入口 配置 && 实践总结

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过