webpack多页面打包方法工具和模板

本文详细介绍了使用webpack进行多页面应用打包的方法,包括目录结构、组件写法、页面引入、webpack配置以及工具封装。重点讲解了如何设置entry和htmlWebpackPlugins,并提供了具体的package.json和index.js代码示例。
摘要由CSDN通过智能技术生成

webpack多页面打包方法工具和模板

本文介绍一个多页面打包方法工具的封装和使用,项目代码见webpack_template

打包前后目录结构效果

在这里插入图片描述

  1. 打包目标为src目录,src目录下又分两类:

第一类如api这类文件夹,属于直接复制即可,此外还有一些静态资源如images等;

第二类是pages,即业务文件夹,下分为对应的personalCenter、shoppingMall等二级目录,即个人中心模块/商城模块,每个模块目录下的index文件即该模块主页,子目录如productDetails文件即商品模块子页面的商品详情;

在这里插入图片描述

  1. 打包后的文件输入在dist文件夹下:

第一类文件直接复制到dist文件,第二类文件仅保留模块目录结构(不再有src/pages层),如,

dist/api/service.js

dist/shoppingMall/index.html

dist/shoppingMall/productDetails/index.html

方法工具的使用模板

组件写法

商品组件html:src/components/shoppingMall/demo/index.html

<div class="demo">
    this is shoppingMall components demo
</div>

商城组件css:src/components/shoppingMall/demo/index.css

.demo {
    color: green;
}
页面引入

商品详情页html:src/pages/shoppingMall/productDetails/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <%= require('raw-loader!components/shoppingMall/demo/index.html') %>
</body>
</html>

商城详情页css:src/pages/shoppingMall/productDetails/index.css

@import "~components/shoppingMall/demo/index.css";
body {
    background-color: gold;
}

商城详情页js:src/pages/shoppingMall/productDetails/index.js

import './index.css'
webpack配置

引入webpack-utils,example示例中即const utils = require('../index.js');

const HtmlWebpackPlugin = require("html-webpack-plugin");
// 给setEntryAndHtmlPlugin方法传入pages目录命数组,其中首页需放在名为home的文件夹下
const pagesFile = ['shoppingMall', 'personalCenter', 'home'];
const { entry, htmlWebpackPlugins } = utils.setEntryAndHtmlPlugin(pagesFile);
// webpack配置入口和插件
module.exports = {
    entry: entry,
    plugins: [].concat(htmlWebpackPlugins.map(html=>{return new HtmlWebpackPlugin(html)})),
}

工具封装

package.json
  1. npm i glob,用于同步的获取文件列表
index.js
  1. 该文件即我们的多页面打包方法文件,导出一个setEntryAndHtmlPlugin方法
exports.setEntryAndHtmlPlugin = function (entryFile) {
    // 处理自定义目录
    let custom = handleCustom(entryFile);

    // 整合配置
    const entry = {};
    const htmlWebpackPlugins = [];
    custom.forEach((v)=>{
        Object.assign(entry,v.entry)
        htmlWebpackPlugins.push(v.htmlWebpackPlugins)
    })
    return {
        entry,
        htmlWebpackPlugins,
    };
};

该方法接收一个Array数组类型的参数,即需要打包的的src/pages下的自定义目录列表。

返回一个对象,entry属性的值对应webpack配置的entry入口,
htmlWebpackPlugins属性的值为html-webpack-plugin插件生成实例的配置对象。

setEntryAndHtmlPlugin方法主要调用了handleCustom方法,handleCustom方法接收自定义目录列表作为参数,同样返回一个Array数组,数组的每一项都为如下格式的对象,代表了一个需要打包的页面。

随后setEntryAndHtmlPlugin方法整合了handleCustom返回的数组,返回最终结果。

{
    entry: entry,
    htmlWebpackPlugins: html,
}
  1. 在讲述handleCustom前,我们先在index.js中增加声明如下常量和方法
const glob = require("glob");
const path = require("path");
const projectRoot = process.cwd();

function resloveDirs(dir, type) {
    if (type === 1) {
        // 处理自定义目录下的子目录
        return glob.sync(path.join(projectRoot, `src/pages/${dir}/*/index.js`));
    } else if (type === 2) {
        // 处理自定义目录下的index
        return glob.sync(path.join(projectRoot, `src/pages/${dir}/index.js`));
    } else {
        return [];
    }
}

glob:用于同步的获取文件列表

path:用于处理路径

projectRoot:为进程执行时的工作目录

resloveDirs:该方法接收两个参数,dir即我们自定义目录列表的某一项,type用于区分是自定义目录的首页还是子页面

  1. handleCustom方法
//处理自定义入口和模板
function handleCustom(entryFile) {
    let arr = [];

    let paths = entryFile;
    if (!paths.length) return arr;

    for (let i = 0, l = paths.length; i < l; i++) {
        // 处理自定义目录下的index
        let index_dir = resloveDirs(paths[i], 2);
        if(index_dir[0]){
            arr.push(setEntryHtml('index',paths[i],index_dir[0],paths[i] === 'home'? 0 : 2))
        }
        // 处理自定义目录下的子目录
        let dir = resloveDirs(paths[i], 1);
        if (!dir.length) continue;
        let reg = new RegExp(`src\/pages\/${paths[i]}\/(.*)\/index\.js`);
        for (let j = 0; j < dir.length; j++) {
            let match = dir[j].match(reg);
            arr.push(setEntryHtml(match[1],paths[i],dir[j],1))
        }
    }
    return arr;
}

handleCustom方法的入参和反参我们已经说过了,这里讲一下他的主要处理过程。

当没有任何自定义目录时,直接返回空数组。

反之对自定义目录列表进行遍历,分两部分处理:自定义目录的首页和子页面,每一部分通过resloveDirs方法返回的数组长度,我们即可判断是否有匹配的页面。

处理自定义目录的首页,直接调用setEntryHtml方法,将其返回推入结果数组。

处理自定义目录子页面,遍历子目录列表,对每一个子目录通过正则匹配出子目录名,作为setEntryHtml方法的第一个入参,调用setEntryHtml方法,将其返回推入结果数组。

  1. setEntryHtml方法—设置入口和模板

5.1 该方法接收4个参数

match:子目录名或"index"

dirName:为自定义目录列表的某一项

fullpath:为resloveDirs方法返回的某一项,即某个index.js文件的绝对路径

type:0 首页 1 自定义目录的子页面 2 自定义目录的首页

5.2 根据type类型生成各自的配置项

5.2.1 htmlWebpackPlugins配置项(文档)

template:模板文件的位置

filename:输出html文件的文件名

chunks:允许插入到模板中的一些chunk,与entry中打包生成的文件名对应

5.2.2 entry配置项

打包生成的文件名: 对应的打包文件

function setEntryHtml(match,dirName,fullpath,type) {
    let templatePath = type !== 1
                            ? `src/pages/${dirName}/${match}.html`
                            : `src/pages/${dirName}/${match}/index.html`;
    let outputPath = type === 0
                        ? `${match}`
                        : type === 2
                            ? `${dirName}/${match}`
                            : `${dirName}/${match}/index`;
    let html = {
        template: path.join(projectRoot, templatePath),
        filename: `${outputPath}.html`,
        chunks: ["vendors", outputPath],
        hash:true,
        minify: {
            html5: true,
            collapseWhitespace: true,
            preserveLineBreaks: false,
            minifyCSS: true,
            minifyJS: true,
            removeComments: true,
        },
    }
    let entry={}
    entry[outputPath]=fullpath;
    return {
        entry: entry,
        htmlWebpackPlugins: html,
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值