整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

美团跨端一体化富文本管理技术实践

美团跨端一体化富文本管理技术实践

了减少产品和前端开发人员之间的矛盾,不断降本提效,美团医药技术部构建了跨端一体化富文本管理平台Page-佩奇。本文系统介绍了该平台的定位、设计思路、实现原理以及取得的成效。希望这些实战经验与总结,能给大家带来一些启发或帮助。

一、引言

在互联网圈,开发和产品经理之间相爱相杀的故事,相信大家都有所耳闻。归根结底,往往都是从简单的改需求开始,然后你来我往、互不相让,接着吵架斗嘴,最后导致矛盾不断升级,甚至带来比较严重的后果。

图1

在这种背景下,如果把一些功能相对简单的、需求变动比较频繁的页面,直接交给产品或者运营自己去通过平台实现,是不是就可以从一定程度上减少产品和开发人员之间的矛盾呢?

二、背景

当然上述的情况,美团也不例外。近些年,美团到家事业群(包括美团外卖、美团配送、闪购、医药、团好货等)的各个业务稳步发展,业务前端对接的运营团队有近几十个,每个运营团队又有不同的运营规则,这些规则还存在一些细微的样式差别,同时规则内容还会随着运营季节、节日、地理位置等进行变化和更新。这些需求具体来说有以下几个特点:

  1. 需求量大:业务稳步发展,业务需求不断叠加,甚至部分业务呈指数级增长,且业务方向涉及到一些业务规则、消息通知、协议文档、规则介绍等需求。
  2. 变更频繁:面对市场监管和法务的要求,以及新业务调整等因素的影响,会涉及到需求的频繁变更,像一些业务FAQ、产品介绍、协议文档、业务规则、系统更新日志等页面,需要做到快速响应和及时上线。
  3. 复杂度低:这些页面没有复杂的交互逻辑,如果能把这些简单的页面交给运营/产品去实现,开发人员就能有更多的时间去进行复杂功能的研发。
  4. 时效性高:临时性业务需求较多,且生命周期较短,具有定期下线和周期性上线等特点。

基于以上特点,为了提高研发效率,美团医药技术部开始构建了一个跨端一体化富文本管理平台,希望提供解决这一大类问题的产研方案。不过,部门最初的目标是开发一套提效工具,解决大量诸如帮助文档、协议页、消息通知、规则说明等静态页面的生产与发布问题,让产品和运营同学能够以所见即所得的方式自主完成静态页面制作与发布,进而缩短沟通成本和研发成本。

但是,随着越来越多业务部门开始咨询并使用这个平台,我们后续不断完善并扩充了很多的功能。经过多次版本的设计和迭代开发后,将该平台命名为Page-佩奇,并且注册成为美团内部的公共服务,开始为美团内部更多同学提供更好的使用体验。

本文将系统地介绍Page-佩奇平台的定位、设计思路、实现原理及取得成效。我们也希望这些实战经验与总结,能给更多同学带来一些启发和思考。

三、跨端一体化富文本管理解决方案

3.1 平台定位

我们希望将Page-佩奇打造成一款为产品、运营、开发等用户提供快速一站式发布网页的产研工作台,这是对该平台的一个定位。

  • 对产品运营而言,他们能够可视化地去创建或修改一些活动说明、协议类、消息类的文章,无需开发排期,省去向开发二次传递消息等繁琐的流程,也无需等待漫长的发布时间,从而达到灵活快速地进行可视化页面的发布与管理。
  • 对开发同学而言,他们能够在线编写代码,并实现秒级的发布上线,并且支持ES 6、JavaScript 、Less、CSS语法,我们还提供了基础的工具、图表库等,能够生成丰富多样的页面。帮助开发同学快速实现数据图表展示,设计特定样式,完成各种交互逻辑等需求。
  • 对项目管理方而言,他们能够清晰地看到整个需求流转状态和开发日志信息,为运营管理提供强大的“抓手”。

一般来讲,传统开发流程是这样的:首先产品提出需求,然后召集研发评审,最后研发同学开发并且部署上线;当需求上线之后,如果有问题需要反馈,产品再找研发同学进行沟通并修复,这种开发流程也是目前互联网公司比较常见的开发流程。

图2 传统开发流程图

而美团Page-佩奇平台的开发流程是:首先产品同学提出需求,然后自己在Page平台进行编辑和发布上线,当需求上线之后有问题需要反馈,直接就能触达到产品同学,他们通常可自行进行修复。如果需求需要定制化,或者需要做一些复杂的逻辑处理,那么再让研发人员配合在平台上进行开发并发布上线。

图3 Page佩奇平台开发流程图

简单来说,对那些功能相对简单、需求变动比较频繁的页面,如果用传统的开发流程将会增加产研沟通和研发排期成本,因此传统方案主要适用于功能复杂型的需求。而Page佩奇平台开发流程,并不适合功能复杂型的需求,特别适用于功能相对简单、需求变动比较频繁的页面需求。

综上所述,可以看出这两种开发流程其实起到了一个互补的作用,如果一起使用,既可以减少工作量,又可以达到降本提效的目的。

3.2 设计思路

我们最初设计Page-佩奇平台的初心其实很简单,为了给产品和运营提供一个通过富文本编辑器快速制作并发布网页的工具。但是,在使用的过程中,很多缺陷也就慢慢地开始暴露,大致有下面这些问题:

  1. 简单的富文本编辑器满足不了想要的页面效果,怎么办?
  2. 如果能导入想要的模板,是否会更友好?
  3. 怎么查看这个页面的访问数据?如何能监控这个页面的性能问题?
  4. 发布的页面是否有存在安全风险?

于是,我们针对这些问题进行了一些思考和调研:

  • 当富文本编辑器满足不了想要实现的效果的时候,可以引入了WebIDE编辑器,可以让研发同学再二次编辑进行实现。
  • 一个系统想要让用户用得高效便捷,那么就要完善它的周边生态。就需要配备完善的模板素材和物料供用户灵活选择。
  • 如果用户想要了解页面的运行情况,那么页面运行的性能数据、访问的数据也是必不可少的。
  • 如果发布的内容存在不当言论,就会造成不可控的法律风险,所以内容风险审核也是必不可少的。

实现一个功能很容易,但是想要实现一个相对完善的功能,就必须好好下功夫,多思考和多调研。于是,围绕着这些问题,我们不断挖掘和延伸出了一系列功能:

  1. 富文本编辑:强大而简单的可视化编辑器,让一切操作变得简单、直观。产品同学可以通过编辑器自主创建、编辑网页,即使无程序开发经验也可以通过富文本编辑器随意操作,实现自己想要的效果,最终可以实现一键快速发布上线。
  2. WebIDE:定制化需求,比如,与客户端和后端进行一些通信和请求需求,以及针对产品创建的HTML进行二次加工需求,均可以基于WebIDE通过JavaScript代码实现。具备专业开发经验的同学也可以选择通过前端框架jQuery、Vue,Echarts或者工具库Lodash、Axios实现在线编辑代码。
  3. 页面管理:灵活方便地管理页面。大家可以对有权限的文档进行查看、编辑、授权、下线、版本对比、操作日志、回滚等操作,且提供便捷的文档搜索功能。
  4. 模板市场:丰富多样的网页模板,简易而又具备个性。模板市场提供丰富的页面模板,大家可选择使用自己的模板快速创建网页,且发布的每个页面又可以作为自己的模板,再基于这个模板,可随时添加个性化的操作。
  5. 物料平台:提供基础Utils、Echart、Vue、jQuery等物料,方便开发基于产品的页面进行代码的二次开发。
  6. 多平台跨端接入:高效快捷地接入业务系统。通过通信SDK,其他系统可以快速接入Page-佩奇平台。同时支持以HTTP、Thrift方式的开放API供大家选择,支持客户端、后端调用开放API。
  7. 内容风险审核:严谨高效的审核机制。接入美团内部的风险审核公共服务,针对发布的风险内容将快速审核,防止误操作造成不可控的法律风险。
  8. 数据大盘:提供页面的数据监测,帮助大家时刻掌握流量动向。接入美团内部一站式数据分析平台,帮助大家安全、快速、高效地掌握页面的各种监测数据。
  9. 权限管理:创建的每个页面都有相对独立的权限,只有经过授权的人才能查看和操作该页面。
  10. 业务监控:提供页面级别JavaScript错误和资源加载成功率等数据,方便开发排查和解决线上问题。

功能流程图如下所示:

图4 Page佩奇平台功能流程图

3.3 实现原理

3.3.1 基础服务

Page-佩奇平台的基础服务有四个部分,包括物料服务、编译服务、产品赋能、扩展服务。

图5 整体架构图

3.3.2 核心架构

图6 核心架构图

Page-佩奇平台核心架构主要包含页面基础配置层、页面组装层以及页面生成层。我们通过Vuex全局状态对数据进行维护。

  • 页面基础配置层主要提供生成页面的各种能力,包括富文本的各种操作能力、编辑源码(HTML、CSS、JavaScript)的能力、自定义域名配置、适配的容器(PC/H5)、发布环境等。
  • 页面组装层则会基于基础配置层所提供的的能力,实现页面的自由编辑,承载大量的交互逻辑,用户的所有操作都在这一层进行。 业务PV和UV埋点,错误统计,访问成功率上报。自动适配PC和移动端样式。内网页面显示外网不可访问标签。
  • 页面生成层则需要根据组装后的配置进行解析和预处理、编译等操作,最终生成HTML、CSS、JavaScript渲染到网页当中。

3.3.3 关键流程

图7 关键流程图

如上图7所示,平台的核心流程主要包含页面创建之后的页面预览、编译服务、生成页面。

  • 页面预览:创建、编辑之后的页面,将会根据内容进行页面重组,对样式和JavaScript进行预编译之后,对文本+JavaScript+CSS进行组装,生成HTML代码块,然后将代码块转换成Blob URL,最终以iframe的方式预览页面。
  • 编译服务:文件树状结构和代码发送请求到后端接口,基于Webpack将Less编译成CSS,ES 6语法编译成ES 5。通用物料使用CDN进行引入,不再进行二次编译。
  • 生成页面:当创建、编辑之后的页面进行发布时,服务端将会进行代码质量检测、内容安全审查、代码质量检测、单元测试、上传对象存储平台、同步CDN检测,最终生成页面链接进行访问。

3.3.4 多平台接入

Page-佩奇平台也可以作为一个完善的富文本编辑器供业务系统使用,支持内嵌到其他系统内。作为消息发布等功能承载,减少重复的开发工作,同时我们配备完善的SDK供大家选择使用。通过Page-SDK可以直接触发Page平台发布、管理等操作,具体的流程如下图所示:

图8 Page-SDK流程图

3.3.5 OPEN API

在使用Page-佩奇平台的时候,美团内部一些业务方提出想要通过Page-佩奇平台进行页面的发布,同时想要拿到发布的内容做一些自定义的处理。于是,我们提供了Open API开放能力,支持以HTTP和Thrift两种方式进行调用。下面主要讲一下Thrift API实现的思路,首先我们先了解下Thrift整体流程:

图9 Thrift整体流程图

Thrift的主要使用过程如下:

  1. 服务端预先编写接口定义语言 IDL(Interface Definition Language)文件定义接口。
  2. 使用Thrift提供的编译器,基于IDL编译出服务语言对应的接口文件。
  3. 被调用服务完成服务注册,调用发起服务完成服务发现。
  4. 采用统一传输协议进行服务调用与数据传输。

那么下面我们具体讲下,Node语言是如何实现和其他服务语言实现调用的。由于我们的服务使用的Node语言,因此我们的Node服务就充当了服务端的角色,而其他语言(Java等)调用就充当了客户端的角色。

图10 Thrift使用详细流程图

  • 生成文件:由服务端定义IDL接口描述文件,然后基于IDL文件转换为对应语言的代码文件,由于我们用的是Node语言,所以转换成JavaScript文件。
  • 服务端启动服务:引入生成的JavaScript文件,解析接口、处理接口、启动并监听服务。
  • 服务注册:通过服务器内置的“服务治理代理”,将服务注册到美团内部的服务注册路由中心(也就是命名服务),让服务可被调用方发现。
  • 数据传输:被调用时,根据“服务治理服务”协议序列化和反序列化,与其他服务进行数据传输。

目前,美团内部已经有相对成熟的NPM包服务,已经帮我们实现了服务注册、数据传输、服务发现和获取流程。客户端如果想调用我们所提供的的Open API开放能力,首先申请AppKey,然后选择使用Thrift方式或者HTTP的方式,按照所要求的参数进行请求调用。

3.4 方案实践

3.4.1 H5协议

能力:富文本编辑。 描述:提供富文本可视化编辑,产品和运营无需前端就可以发布和二次编辑页面。 场景:文本协议,消息通知,产品FAQ。

具体案例:

图11 H5静态文本协议案例

3.4.2 业务自定义渲染

能力:开放API(Thirft + HTTP)。 描述:提供开放API,支持业务自定义和样式渲染到业务系统,同时解决了iframe体验问题。 场景:客户端、后端、小程序的同学,可根据API渲染文案,实现动态化管理富文本信息。

具体案例:

小程序使用组件、Vue使用v-html指令实现动态化渲染商品选择说明。

    {
    "code": 0,
    "data": {
      "tag": "苹果,标准",
      "title": "如何挑选苹果",
      "html": "<h1>如何挑选苹果</h1>><p>以下标准可供消费者参考</p><ul><li>酸甜</li><li>硬度</li></ul>",
      "css": "",
      "js": "",
      "file": {}
    },
    "msg": "success"
}

3.4.3 投放需求

能力:WebIDE代码编辑。 描述:开发基于WebIDE代码开发工作,基于渠道和环境修改下载链接,能够做到分钟级支撑。 场景:根据产品创建静态页面进行逻辑和样式开发。

具体案例:

    var ua=window.navigator.userAgent
    var URL_MAP={
        ios: 'https://apps.apple.com/cn/app/xxx',
        android: 'xxx.apk',
        ios_dpmerchant: 'itms-apps://itunes.apple.com/cn/app/xxx'
    }
    
    if (ua.match(/android/i)) location.href=URL_MAP.android
    if (ua.match(/(ipad|iphone|ipod).*os\s([\d_]+)/i)) {
        if (/xx\/com\.xxx\.xx\.mobile/.test(ua)) {
            location.href=URL_MAP.ios_dpmerchant
        } else {
            location.href=URL_MAP.ios
        }
    }

3.4.4 客户端通信中间页

能力:WebIDE代码编辑 + 物料平台。 描述:通过物料平台,引入公司客户端桥SDK,可以快速完成客户端通信需求。方便前端调试客户端基础桥功能。 场景:客户端跳转,通信中间页。

具体案例:

    // 业务伪代码
    XXX.ready(()=> {
        XXX.sendMessage({
           sign: true,
            params: {
                id: window.URL
            }
        }, ()=> {
            console.error('通信成功')
        }, ()=> {
            console.error('通信失败')
        })
    })

3.4.5 业务系统内嵌Page

能力:提供胶水层Page-SDK,连接业务系统和Page。 描述:业务系统与Page-佩奇平台可进行通信,业务系统可调用Page发布、预览、编辑等功能,Page可返回业务系统页面链接、内容、权限等信息。减少重复前后端工作,提升研发效率。 场景:前端富文本信息渲染,后端富文本信息管理后台。

具体案例:

图12 业务系统内嵌Page案例

3.5 业务成绩

截止目前数据统计,Page佩奇平台生成网页5000多个,编辑页面次数16000多次,累计页面访问PV超过8260万。现在,美团已经有十多个部门和三十多条业务线接入并使用了Page佩奇平台。

图13 Page平台每日生成页面统计


四、总结与展望

富文本编辑器和WebIDE不仅是复杂的系统,而且还是比较热门的研究方向。特别是在和美团的基建结合之后,能够解决团队内部很多效率和质量问题。这套系统还提供了语法智能提示、Diff对比、前置检测、命令行调试等功能,不仅要关注业务发布出去页面的稳定性和质量,更要有内置的一系列研发插件,主动帮助研发提高代码质量,降低不必要的错误。

经过长期的技术和业务演进,Page-佩奇平台已经能够有效地帮助研发人员大幅提升开发效率,具备初级的Design To Code能力,但是仍有许多业务场景值得去我们探索。我们也期待优秀的你参与进来,一起共同建设。

  • WebIDE融合:完善基础设施建设和功能需求,更好地支持Vue、React、ES 6、TS、Less语法,预览模式采用浏览器编译,能有效地提高预览的速度,发布使用后端编译的模式。
  • 研发流程链路:针对代码进行有效评估,包括ESlint、代码重复率、智能提示是否可以三方库替代。出具开发代码质量、业务上线的质量报告。
  • 综合研发平台:减少团队同学了解整体基建的时间成本,内置了监控、性能、任务管理等功能,提升业务开发效率。建设自动化日报、周报系统,降低非开发工作量占比。
  • 物料开放能力:接入公共组件平台,沉淀更多的物料,快速满足产品更多样化的需求。

五、作者简介

高瞻、宇立、肖莹、浩畅,来自美团医药终端团队。王咏、陈文,来自美团闪购终端团队。

六、招聘信息

美团医药长期招聘Android、iOS、FE前端工程师,坐标在北京和成都。感兴趣的同学可将简历发送至:sunyuli@meituan.com(邮件主题请注明:美团医药终端)。

| 本文系美团技术团队出品,著作权归属美团。欢迎出于分享和交流等非商业目的转载或使用本文内容,敬请注明“内容转载自美团技术团队”。本文未经许可,不得进行商业性转载或者使用。任何商用行为,请发送邮件至tech@meituan.com申请授权。

天来聊聊定制你的bootstrap文件,换句话说就是修改css文件,大家知道bootstrap文件是有less书写的,好吧,我们从源头开始吧!

1、下载bootstrap源文件:

在bootstrap中文网上下载源码,不要选错呀。

2、解压后看到less文件夹,打开,找到variables.less文件,这个文件基本上存的都是变量;用sublime打开。

3、看到了从第4行开始:

4、我们今天就说这一段,基本的less语法,等说完了,再说如何解析成css文件。

  • 第1,2,3行是注释,在less中,注释有2中,一种是css的格式注释,一种是//注释;

    区别1:/**/是多行注释 // 是单行注释

    区别2:/**/编译的时候写入css文件 //注释的不写入css文件

  • @gray-base: #000; 定义一个变量@gray-base值为#000;

  • @gray-darker: lighten(@gray-base, 13.5%); // #222

    定义一个变量@gray-darker 值是多少呢?

  • 先看(@gray-base, 13.5%); 上面的变量
    • @gray-base 是#000;16进制是 0;

    • 0的13.5%,黑色的就是 22呀!

    • 所以 lighten默认的就是#222;

    • 整个是什么意思呢? 就是@gray-darker的值为 lighten(@gray-base, 13.5%);,如果变量没有传参数,那么就是默认的222;如果传了参数,则为(@gray-base, 传入的参数)

  • 我们在392行,可以看到“反色导航条”颜色定义的代码:

  • 它的后面传了个参数为15%,值是多少你自己算算。

这样的好处是什么呢?

你想想,你在做一个项目的时候,客户今天说就定这个颜色了,过了几天,改了,换颜色了!

如果你用css写的,O(∩_∩)O~,你就挨个改吧。如果你用less写的,只需要修改一处,就可以了,分分钟的事!惬意吧!

今天就先说到这里,改天说说如何让less文件编译为css文件!

.环境安装

1.安装node: 官网

2.配置cnpm(非必须)

设置淘宝镜像:npm install -g cnpm --registry=https://registry.npm.taobao.org,10分钟同步官网一次。

或者可以使用npm config set registry https://registry.npm.taobao.org来改变npm默认下载地址

2.初始化工程

1.初始化工程目录

mkdir my_demo
cd my_demo
npm init

回车会生产一个npm目录,只包含一个package.json,创建src目录

mkdir src

2.配置工程

(1)首先安装webpack和webpack-cli

npm i -D webpack webpack-cli -g

(2)新建并配置webpack(entry, output, loader, plugin, mode)

const path=require('path');
 4 module.exports={
 5     // 项目入口,webpack从此处开始构建
 6     entry: {
 7         main: path.join(__dirname, 'src/index.js'), // 指定入口,可以指定多个。参考webpack文档
 8     },
 9     output: {
10         path: path.join(__dirname, "dist"), // bundle生成(emit)到哪里
11         filename: "bundle.js", // bundle生成文件的名称
12     },
13 }
  • 这样就完成了最简单的webpack配置文件。相应的我们需要在src目录下新建一个index.js 文件。
  • 接下来在命令行输入 webpack --config ./webpack.config.js就可以输出dist文件夹。
  • 为了方便起见,通常我们会在package.json里配置脚本命令。在scripts标签下,添加一句"build": "webpack --config ./webpack.config.js"这样,我们就可以通过npm run build/yarn build完成webpack打包。

(3)配置开发应用服务器

正常情况下,我们需要以应用服务器打开我们的网页,webpack-dev-server提供了一个简单的web服务器,并且能够实时重新加载。指南 首先需要安装webpack-dev-server

npm i -D webpack-dev-server
module.exports={
    entry: './src/index.js',
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js',
    },
    devServer: {
        contentBase: './dist',
    },
    ...
}

这段配置告诉webpack-dev-server,在默认host和port(8080)下建立服务,并将contentBase目录下的目录,作为可访问文件。
接下来让我们的服务器跑起来
webpack --mode production --config ./webpack.config.js,在package.json配置命令脚本:

可能会有报错,webpack-cli @4的版本不兼容,降到@3就可以啦

 "scripts" : {
2     "start": "webpack-dev-server --mode development --open",
3     "build: "webpack --mode production --config ./webpack.config.js"
4 }

其中mode为模式,webpack会有相应优化


3.安装react,babel

安装react全家桶,安装jsx转换工具babel

npm install react react-dom react-router-dom -S
npm install babel-core babel-loader babel-preset-env babel-preset-react -D

配置webpack使其生效

module.exports={
    // ...省略
    module: {
        rules: [

{
    test: /\.(js|jsx)$/, // babel7开始支持编译ts,tsx
    exclude: /node_modules/,
    enforce: 'pre',
    use: [{
        loader: 'babel-loader',
    }, {
        loader: 'eslint-loader', // 指定启用eslint-loader,需安装
        options: {
            formatter: require('eslint-friendly-formatter'),  // 安装
            emitWarning: false
        }
    }]
},
    ]
}

babel-loader的配置可以在rules中loader option配置,也可以单独一个.bablerc或babel.config.js的文件放在根目录下,babel会自动读取配置

{
  "presets": ["env","react"],
  // antd按需引入
  // "plugins": ["react-hot-loader/babel", ["import", { "libraryName": "antd", "libraryDirectory": "es","style": "css" }], "transform-runtime"]
}

扩展:babel 7.x 以上开始支持两种类型的配置文件, 分别是.babelrcbabel.config.js ,在官方的描述里:

babel.config.js 当前项目维度 (Project Wide)的配置文件,相当于一份全局配置,如果 babel 决定应用这个配置文件,则一定会应用到所有文件的转换。

.babelrc 相对文件(File Relative)的配置文件, babel 决定一个 js 文件应用哪些配置文件时,会执行如下策略: 如果要转换的这个 js 文件在当前项目内,则会先递归向上搜索最近的一个 .babelrc 文件(直到遇到package.json目录),将其与全局配置合并。如果这个 js 文件不在当前项目内,则只应用全局配置,忽略与这个文件相关的 .babelrc

这两个我更愿意将其称为全局配置 (babel.config.js) 和局部配置 (.babelrc) 便于理解一些。

参考链接:https://zhuanlan.zhihu.com/p/367724302

4.添加常用loader

(1)样式loader:

前置安装style-loader、less-loader/scss-loader、css-loader、postcss-loader。

  • less-loader是将less编译成css的loader
  • postcss是将css加上浏览器Hack的loader
  • css-loader用于在js中import、require等方法引入css
  • style-loader用于将css最终写入html文件。


test: /\.(css|less)$/,
exclude: /node_modules/,
include: /src/,
use: [
    {loader: "style-loader"},
    {
        loader: 'css-loader',
        options: {
            minimize: process.env.NODE_ENV==='production',
            importLoaders: 2,
            localIdentName: '[name]-[local]-[hash:base64:5]',
            modules:true
        }
    }, {
        loader: 'postcss-loader',
        options: {           // 如果没有options这个选项将会报错 No PostCSS Config found
            plugins: (loader)=> [
                require('autoprefixer')(), //CSS浏览器兼容
            ]
        }
    },{
        loader: 'less-loader',
        options: {
            javascriptEnabled: true,
        }
    }],

(2)图片资源 file-loader/url-loader

url-loader里的limit参数可以指定小于配置参数的文件转换成base64编码的文件,其余的生成一个可配置hash的单独文件(file-loader的作用),这里也指出了两者的不同之处。

3.工程优化

1.单独打包样式文件

# for webpack 4
npm install --save-dev mini-css-extract-plugin
# for webpack 3
npm install --save-dev extract-text-webpack-plugin
# for webpack 2
npm install --save-dev extract-text-webpack-plugin@2.1.2
# for webpack 1
npm install --save-dev extract-text-webpack-plugin@1.0.1

extract-text-webpack-plugin用法

const ExtractTextPlugin=require("extract-text-webpack-plugin");

module.exports={
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
}

mini-css-extract-plugin用法

const MiniCssExtractPlugin=require('mini-css-extract-plugin');

module.exports={
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
};

2.为打包后的文件增加hash

如果浏览器加载发现远端文件没有发生变化时,将会启用缓存,导致新修改的页面并没有同步,这时候为了避免缓存,我们就需要让每次打包后的文件有不同的文件名,以减少缓存。

// webpack.config.js -> output
output: {
    path: path.join(__dirname, "dist"),
    publicPath: '/',
    filename: "js/[name]-[hash]" + ".js",
    chunkFilename: "js/[name]-[hash]" + ".js",
},

同样抽取的css文件也可以类似命名hash

3.html-webpack-plugin

生成一个自动引入我们生成的文件的新模板。 当我们在生成有 hash 标识符的 css,js时非常方便

4.提取公共代码

splitChunks:提取公共代码,防止代码被重复打包,拆分过大的js文件,合并零散的js文件。

具体使用翻看专题