react+webpack4.x搭建前端项目(五)多页面配置

前言

我们接着上一篇文章react+webpack4.x搭建前端项目之配置抽取和区分环境来进行多页面打包的配置

这里小编推荐一个福利,更多精彩内容请点击链接,点击这里

首先修改src下的代码,项目的结构目录

QQ截图20191213143525.png

源码见修改src下代码,添加测试a,b??橥暾?.0.2

开发环境多页面的配置

新建build/module-entry.js,获取额外打包的??槊腿肟趀ntry配置

const glob = require("glob")

// 获取各个??槊?function getModuleList(){
    const moduleList = glob.sync("././src/modules/*");
    for(let index = 0 ; index < moduleList.length ; index++){
        const item = moduleList[index];
        const tmpList = item.split("/");
        moduleList[index] = tmpList[tmpList.length-1];
    }
    return moduleList;
}

// 获取webpack entry
function getBuildEntry(){
    const moduleList = getModuleList();
    let entry = {};
    for(let index in moduleList){
        const moduleName = moduleList[index]
        entry[moduleName] = "./src/modules/" + moduleName + "/index.js"
    }
    // 额外添加./src/index的配置(把这个也当做一个页面)
    entry["app"] = "./src/index.js"
    return entry
}
module.exports = {
    getModuleList,
    getBuildEntry,
};

然后我们修改webpack.dev.config.js

组装htmlwebpackplugin多页面模板和输出模板

const { getModuleList , getBuildEntry} = require("./module-entry")

// 获取各个???const moduleList = getModuleList();

const HtmlWebpackPluginList = [];
for(let index in moduleList){
    const moduleName = moduleList[index]
    HtmlWebpackPluginList.push(new HtmlWebpackPlugin({
        filename: utils.resolve('./../dist/'+ moduleName+ '/index.html'), // html模板的生成路径
        template: utils.resolve("./../src/modules/" + moduleName + "/index.html"),//html模板
        inject: true, // true:默认值,script标签位于html文件的 body 底部
        chunks: [moduleName],  // 注入哪个名称bundel
    }))
}

最后把HtmlWebpackPluginList放入plugins属性下,在plugins数组最后加如下代码

.concat(HtmlWebpackPluginList)

修改entry属性

entry: getBuildEntry(),

执行npm run dev
浏览器打开http://localhost:8081,结果如下图

QQ截图20191213161552.png

发现怎么是b页面的内容?

那么是为什么呢?经过排查,打开控制台选择elements看到如下图

QQ截图20191213161753.png

index.html注入了所有bundlea,b模块(页面)的bundle也注入到html页面中,b模块的bundle在最后边,把前边的覆盖了。这就是问题的根源。

这时候我们需要修改webapck.dev.config.js默认HtmlWebpackPlugin的实例的参数,新增chunks: ['app']

new HtmlWebpackPlugin({
    filename: utils.resolve('./../dist/index.html'), // html模板的生成路径
    template: 'index.html',//html模板
    chunks: ['app'], // 至注入app和app相关的bundle
    inject: true, // true:默认值,script标签位于html文件的 body 底部
}),

这时候重新运行成功解决!


QQ截图20191213162054.png

然后我们打开http://localhost:8081/ahttp://localhost:8081/b页面正常显示。

QQ截图20191213162633.png
QQ截图20191213162649.png

但是存在一个问题!点击二级路由的时候也可以正常显示,但是我们直接打开或者刷新二级路由的时候(http://localhost:8081/a/test)时候发现页面显示成http://localhost:8081这个页面了

因为这里我们设置的webpack-dev-serverhistoryApiFallback是true,那么它就把所有的地址全部重定向到根目录的index.html,也就会重定向到http://localhost:8081打开的页面了,然后在这下边寻找路由进行匹配

怎么解决呢?

historyApiFallback提供的有一个rewrites属性,可以使用如rewrites选项进一步控制此行为

详细使用请看官方文档

我们这里需要构建rewrites内容

// 需要在开发环境重写的规则数组
const rewrites = [];  // webpack-dev-server的historyApiFallback中使用
for(let index in moduleList){
    const moduleName = moduleList[index]
    // 以模块名开头的路径,重定向到 改??橄碌膇ndex.html模板文件 比如路径一以/a开头,会重定向到a??橄碌膇ndex.html 
    rewrites.push({
        from:new RegExp('^\/' + moduleName), 
        to:utils.resolve('/' + moduleName +'/index.html')
    })
}

最后修改historyApiFallback

historyApiFallback: {
    rewrites: rewrites
},

重新运行npm run dev,再次刷新http://localhost:8081/a/test,页面显示正常。那么开发环境的多页面配置已经完成喽

打包环境多页面的配置

和上边的配置差不多,修改webapck.prod.config.js,只是对于打包环境添加了压缩代码的配置项

const { getModuleList , getBuildEntry} = require("./module-entry")

// 获取各个???const moduleList = getModuleList();

const HtmlWebpackPluginList = [];
for(let index in moduleList){
    const moduleName = moduleList[index]
    HtmlWebpackPluginList.push(new HtmlWebpackPlugin({
        filename: utils.resolve('./../dist/'+ moduleName+ '/index.html'), // html模板的生成路径
        template: utils.resolve("./../src/modules/" + moduleName + "/index.html"),//html模板
        inject: true, // true:默认值,script标签位于html文件的 body 底部
        //  html 文件进行压缩
        chunks: [moduleName,'vendors'],  // 必须指定,不然会把多有打包的东西插入html模板当中
        minify: {
            removeComments: true,               //去注释
            collapseWhitespace: true,           //压缩空格
            removeAttributeQuotes: true         //去除属性引用
        },
    }))
}

最后把HtmlWebpackPluginList放入plugins属性下,在plugins属相后加如下代码

.concat(HtmlWebpackPluginList)

我们还需要修改webapck.prod.config.js默认HtmlWebpackPlugin的实例的参数,新增chunks: ['app']

new HtmlWebpackPlugin({
    filename: utils.resolve('./../dist/index.html'), // html模板的生成路径
    template: 'index.html',//html模板
    inject: true, // true:默认值,script标签位于html文件的 body 底部
    chunks: ['app'],  // 注入app名称bundel
    minify: {
        removeComments: true,               //去注释
        collapseWhitespace: true,           //压缩空格
        removeAttributeQuotes: true         //去除属性引用
    }
}),

执行npm run build测试打包结果,dist目录如下:

QQ截图20191213171322.png

通过webpack-bundle-analyzer分析webpack的拆包和bundle包之间的依赖关系

QQ截图20191213171520.png

得出结论:
这种多页面打包方式,在整个项目的基础上打包,webpack会对这些页面的引用的第三方模块进行拆包,导致不同的页面存在相同的bundle包,也就是不同页面存在共用的bundle包。这样的好处是可以减小打包的总体积

抽取HtmlWebpackPluginList

module-entry.js添加工具方法如下

const HtmlWebpackPlugin = require("html-webpack-plugin")
const utils = require("./utils")

// 获取htmlwebpackplugin列表
function getHtmlWebpackPluginList(options={}){
    const moduleList = getModuleList();
    const HtmlWebpackPluginList = [];
    for(let index in moduleList){
        const moduleName = moduleList[index];
        const HtmlWebpackPluginOptions = {
            filename: utils.resolve('./../dist/'+ moduleName+ '/index.html'), // html模板的生成路径
            template: utils.resolve("./../src/modules/" + moduleName + "/index.html"),//html模板
            inject: true, // true:默认值,script标签位于html文件的 body 底部
            chunks: [moduleName],  // 注入哪个名称bundel
        };
        if(options.extract){
            HtmlWebpackPluginOptions = Object.assign(HtmlWebpackPluginOptions,{
                minify: {
                    removeComments: true,               //去注释
                    collapseWhitespace: true,           //压缩空格
                    removeAttributeQuotes: true         //去除属性引用
                },
            })
        }
        HtmlWebpackPluginList.push(new HtmlWebpackPlugin(HtmlWebpackPluginOptions))
    }
    return HtmlWebpackPluginList;
}

导出该方法。然后在webpack.dev.config.js以及webpack.prod.config.js中导入getHtmlWebpackPluginList方法,

const { getModuleList , getBuildEntry,getHtmlWebpackPluginList } = require("./module-entry")

最后.concat(HtmlWebpackPluginList)替换成.concat(getHtmlWebpackPluginList())

然后在把rewrites数组提取,在module-entry.js添加工具方法如下:

// 获取开发环境重定向的规则,只在开发环境中使用
function getRewritesList(){
    // 获取各个???    const moduleList = getModuleList();

    // 需要在开发环境重写的规则数组
    const rewrites = [];  // webpack-dev-server的historyApiFallback中使用
    for(let index in moduleList){
        const moduleName = moduleList[index]
        // 以模块名开头的路径,重定向到 改??橄碌膇ndex.html模板文件 比如路径一以/a开头,会重定向到a??橄碌膇ndex.html 
        rewrites.push({
            from:new RegExp('^\/' + moduleName), 
            to:utils.resolve('/' + moduleName +'/index.html')
        })
    }
    return rewrites;
}

导出该方法,然后为webpack.dev.config.js文件导入getRewritesList方法
···
const { getModuleList , getBuildEntry,getHtmlWebpackPluginList, getRewritesList} = require("./module-entry")
···
historyApiFallback: {rewrites: rewrites}修改成 historyApiFallback: {rewrites: getRewritesList()}

执行npm run build测试打包结果,一切正常!

源码:react+webpack4.x多页面 release-tag-0.0.3

下一篇:react+webpack4.x多??榇虬渲?/a>

  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • 前言 react+webpack4搭建前端项目分为三个章节。链接如下。目的是实现从零搭建一个react后台管理系统...
    小猿_Luck_Boy阅读 21,422评论 33 56
  • 前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,...
    BetterChen阅读 1,946评论 0 3
  • 最近感觉自己越来越像一个API调用程序员,很多基础的原理以及项目构建都没实际操作过,所以这里动手自己去搭建了一个v...
    Aoyi_G阅读 1,500评论 0 2
  • 1. 新建一个文件夹,命名为 webpack-cli , webpack-cli 就是你的项目名,项目名建议使用小...
    鲁大师666阅读 1,471评论 1 3
  • 目录第1章 webpack简介 11.1 webpack是什么? 11.2 官网地址 21.3 为什么使用 web...
    lemonzoey阅读 1,731评论 0 1