Webpack现今流行的前端打包工具,今儿本人也来分享下自己学习体验。

一、html-webpack-plugin

实现html模板文件的解析与生成

  • 在plugins加入HtmlWebpackPlugin的配置,如果是多个入口文件,则需要对应加入多个HtmlWebpackPlugin功能。
var HtmlWebpackPlugin = require('html-webpack-plugin');
entry:{
ma: './src/ma', /** .:必须要,表示运行时的根目录,否则找不到文件,且不报错 */
mb: './src/mb'
},
output: {
path: './dist',
filename: '[name].js'
},
plugins: [
new HtmlWebpackPlugin({ //可以模板,直接引用files对象,是webpack中state对象
title: '模板A',
chunks: ['ma']
}),
new HtmlWebpackPlugin({
filename: 'mb.html',
title: '模板B',
chunks: ['mb']
})
]

如上代码所示:

  • 两个入口文件,ma与mb,所以配置了两个HtmlWebpackPlugin实例
  • HtmlWebpackPlugin实例配置项:
    • title:模板title
    • filename:输出的html文件名称
    • chunks:包含的文件,可以entry和其他模块chunk的模块,插件导入到 模板时 没有排序,但都是。
    • excludeChunks:被排除的模块
    • chunksSortMode:添加到页面时模块的排序 none|default|function
    • template:模板文件路径所在位置
    • templateContent:一个函数,使用编程语言创建模板
    • inject:js插入位置:body, head
    • 模板可以访问的配置项
      • files:为webpack的stats项,可以在模板文件中使用或者
      • webpackConfig:webpackConfig的配置项
      • options:在模板文件中可以获取的webpack配置项。
  • HtmlWebpackPlugin的事件使用:
事件名称 时机 同步/异步
html-webapck-plugin-before-html-generation 生成htmlPluginData之前触发 async
html-webpack-plugin-before-html-processing htmlPluginData插入到html模板之前触发 async
html-webpack-plugin-alert-asset-tags 验证资源,以及为资源做标记时触发 async
html-webpack-plugin-after-html-processing htmlPluginData插入到html模板之后触发 async
html-webpack-plugin-after-emit 生成html目标文件后触发 async
html-webpack-plugin-alert-chunks 验证资源块信息 sync
var compile = webpack(config);
compile.plugin('compilation', function( compilation, callbak) {
console.log('compilation');
compilation.plugin('html-webpack-plugin-before-html-processing', function (htmlPluginData, callbak) {
console.log(htmlPluginData)
callbak()
})
})

注意:

  • 必须要监测compile的compilation事件
  • 然后在回调compilation事件时,对compilation参数进行plugin的事件的注册 。

二、webpack.optimize.CommonsChunkPlugin

抽取公共模块为一个独立的文件,一是指定的多个模块打成一个包;二是在指定的chunks中抽取公共模块

参数名称 说明
name 可以是字符串,或者是数组,如果指定为entry中一个名称,则只产生此vendor,也可以是一个入口文件列表
filename 输出文件名
minChunks 单独文件最小引用数,如设置3,表示同一个模块只有被3个以外的页面引用时才打包
children 返回,把第三方的vendor包,分解到业务包中
chunks 数组,从指定的源模块提供共用vendor包

1. vendor打成一个包:

entry:{
vendor: ['./src/vendor-jquery', 'bootstrap']
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
})
]

2. CommonsChunkPlugin正确的引入方式

3. 用manifest实现js库的增量更新

如果输出文件名包含hash值,需要引入以下两个插件:

  • HashedModuleIdsPlugin:算hash值
  • 利用CommonsChunkPlugin配置,他是manifest配置模块所有的依赖抽象,如果mainfest不更新,则html会找不到js文件。
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})

三、webpack 样式打包

这其中就包含对css文件、静态资源以及css所包含的资源文件等处理。

  • css-loader:解析css代码
  • style-loader:css代码写入到js文件中
  • 配置代码如下:
loaders:[
{
test:/\.css$/, /*不能加引号*/
loader: 'style-loader!css-loader'
}
]

注意:test后面不能加引号,因这个是正则式

1. 样式文件单独存在,但不能处理静态资源

extract-text-webpack-plugin:抽取样式为单独的文件

  • 参数配置说明
  • ExtractTextPlugin.extract(arg1,arg2,arg3)
    • arg1: 可选参数,传入一个loader,当css没有被抽取的时候可以使用该loader
    • arg2:必填参数,用于编译解析css文件的loader
    • arg3:额外选,暂只可传publicPath,表示当前loader的路径
  • ExtactTextPlugin在Plugins中构造时,至少需要传入一个文件名参数

filename文件名,可以指定一个固定的,也可用[name].[id].[contenthash]来指定文件名,[name]:与entry中的chunk名称一致,[id]:将entry的chunk的id一致;[contenthash]:根据内容生成hash值

参数名称 说明
id 可先参数,插件实例的惟一标识,缺省会自动生成

filename

文件名,可以指定一个固定的,也可用[name].[id].[contenthash]来指定文件名,[name]:与entry中的chunk名称一致,[id]:将entry的chunk的id一致;[contenthash]:根据内容生成hash值
options allchunks:是否将所有额外的chunk都压缩一个文件;disable:禁止使用此插件

代码如下(webpack2.x):

var ExtractTextPlugin = require('extract-text-webpack-plugin');
module:{
loaders:[
{
test:/\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('[name].css')
]

2. file-loader实现css中图片或web字体文件打包

var ExtractTextPlugin = require('extract-text-webpack-plugin');
module:{
loaders:[
{
test:/\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader','postcss-loader']
})
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file-loader?name=fonts/[name].[ext]'
}
]
}

参数说明:

参数名称 说明
name 配置输出文件名,例如:name=[name].[hash].[ext]
name子节点配置说明
[ext] 扩展名
[name] 文件名
[path] 相对于上下文的路径
[hash] hash值
输出配置参数
publicPath 公共资源路径(也可以说是静态资源,就是不参与打包的编译过程的资源)
outputPath 输出资源路径(也可以说是静态资源,就是不参与打包的编译过程的资源)

publicPath和outputPath使用示例代码:

use: "file-loader?name=[name].[ext]&publicPath=assets/foo/&outputPath=app/images/"

3. postcss实现浏览器兼容

代码如下(webpack2.x):

var autoprefixer = require('autoprefixer');
module:{
loaders:[
{
test:/\.css$/,
loader: ExtractTextPlugin.extract({
use: ['css-loader','postcss-loader']
})
}
]
},
plugins: [
new webpack.LoaderOptionsPlugin({
options:{
postcss:[autoprefixer()]
}
})
]
  • webpack2.x不支持自定义配置节点,需要用webpack.LoaderOptionsPlugin加入自定义的插件配置节点。
  • autoprefixer:一个postcss的插件,用于css3的兼容前端处理
    • browsers:配置浏览器的版本,如:browsers:['last 2 versions']

四、热更新

  • 安装 webpack-dev-server
  • 热更新的概念

利用websocket实现,websocket-server识别到html、css和js的改变,就向websocket-client发送一个消息,websocket-client判断如果是html和css就操作dom,实现局部刷新,如果是js就整体刷新。

  • 配置:
var config = require('./webpack.base.conf');
var webpack = require("webpack");
var WebpackDevServer = require('webpack-dev-server');
var compile = webpack(config);
compile.plugin('compilation', function( compilation, callbak) {
compilation.plugin('html-webpack-plugin-before-html-processing', function (htmlPluginData, callbak) {
callbak()
})
})
var isProc = true;
if(isProc){
compile.run(function(err,state){
console.log(err);
})
}else{
var server = new WebpackDevServer(compile,{
contentBase: './build',
hot: true,
inline: true, /*无效*/
historyApiFallback: true
});
server.listen(8080);
}

说明:

  • hot:启动热更新
  • inline:是不会自动刷新网页的,因为此参数只能在cli环境下用
  • 在cli下实现页面自动刷新
webapck-dev-server --hot --inline --config=配置文件

无--inline时,只能在iframe模式下自动刷新:http://localhost:8080/webpack-dev-server/index.html
有--inline时,可以直接访问http://localhost:8080/index.html进行自动刷新

五、cross-env

实现环境变量的定义

"prod": "cross-env NODE_ENV=prod node ./build/dev-server.js",
"dev": "cross-env NODE_ENV=dev node ./build/dev-server.js"

六、示例代码结构说明

前五节说了这么多,也许让你听得云里雾里的。没有代码来说明程序是多么枯燥啊(声明:此代码还包含后一章节的单元测试和e2e测试的配置)。代码结构图以及源码下载地址

  • build:打包配置文件

    • dev-server.js:打包运行入口
    • webpack.base.conf.js:打包plugins节点的配置
    • webpack.core.conf.js:打包module以及entry的基本配置
  • src:源码目录
  • test:测试目录
    • e2e:点到点测试
    • unit:单元测试
    • mocks:mockjs模拟数据

Webpack多入口文件、热更新等体验的更多相关文章

  1. webpack 环境搭建+实现热更新

    让我们一起构建一个小的app 为了便于你更好的了解Webpack带来的好处,我们将会构建一个非常小的app并将资源文件打包.在这个教程中我推荐基于Node4或Node5和NPM3来进行开发,这样就避免 ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  3. 轻松理解webpack热更新原理

    一.前言 - webpack热更新 Hot Module Replacement,简称HMR,无需完全刷新整个页面的同时,更新模块.HMR的好处,在日常开发工作中体会颇深:节省宝贵的开发时间.提升开发 ...

  4. 优化单页面开发环境:webpack与react的运行时打包与热更新

    前面两篇文章介绍初步搭建单页面应用的开发环境: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-router实现单页面应用路由 这 ...

  5. webpack热更新问题和antd design字体图标库扩展

    标题也不知道怎么写好,真是尴尬.不过话说回来,距离上一次写文快两个月了,最近有点忙,一直在开发新项目, 今天刚刚闲下来,项目准备提测.借这个功夫写点东西,把新项目上学到的一些好的干活分享一下,以便之后 ...

  6. webpack 热更新

    1.安装webpack npm install webpack -g  //全局安装 npm install webpack --save-dev  //开发环境 2.使用webpack 创建一个we ...

  7. 搭建带热更新功能的本地开发node server

    引言 使用webpack有一段时间了,对其中的热更新的大概理解是:对某个模块做了修改,页面只做局部更新而不需要刷新整个页面来进行更新.这样就能节省因为整个页面刷新所产生开销的时间,模块热加载加快了开发 ...

  8. vue-vli3创建的项目配置热更新

    vue-vli3创建的项目配置热更新 问题描述:使用vue-cli3创建的项目,修改代码之后,浏览器页面不会自动刷新,然而之前使用webpack初始化的vue项目修改代码之后浏览器会重新加载一下,因为 ...

  9. Vue系列之 => webpack处理样式文件

    处理css文件 安装 npm i style-loader css-loader -D main.js import $ from 'jquery' //Es6中导入模块的方式 import './c ...

随机推荐

  1. PowerPoint实用知识

    纯手打,可能有错别字,使用的版本是office2013 转载请注明出处 http://www.cnblogs.com/hnnydxgjj/p/6347256.html ,谢谢 母版的使用 制作PPT的 ...

  2. leetcode刷题总结

    题外话 今年大三,现正值寒假时间,开学就开始大三下学期的生活了. 在大三临近结束的时间,也就是复习考试的时间里,我每天都会用早上的时间来刷codewars.刚开始玩的时候,一到8kyu的题目如果稍微难 ...

  3. JTable 的使用

    JTable是Swing编程中的一种控件. 一.创建表格控件的各种方式:1) 调用无参构造函数. JTable table = new JTable(); 2) 以表头和表数据创建表格. Object ...

  4. 深圳尚学堂:JavaScript中常见的字符串操作

    快到春节放假了,春节后又是一大波的找工作热潮,在前端实招聘笔试时,必不可免额会考到关于JavaScript中字符串的处理问题.考的不是你会不会,而是你能不能在不借用XX手册或者XX指南再或者百度谷歌的 ...

  5. 打开phpmyadmin显示高级功能尚未完全设置部分功能未激活

    问题:老师,打开phpmyadmin显示高级功能尚未完全设置部分功能未激活,应该如何解决? 这是前一阵子学生问过我的一个问题,今天我就在博客里解答你的疑问吧. 总共三步可以搞定 1.导入相关文件到数据 ...

  6. UINavigationController实现全屏滑动返回功能

    说明: UINavigationController默认在push出的控制器中都有边沿滑动返回功能,但是只能从屏幕左边滑才能返回,若从屏幕中间画并没有效果.下面实现全屏滑动功能. 探究: 系统默认能够 ...

  7. stringBuffer的使用及字符串比较的区别

    /* * 关于equals()和==: 对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true; * 而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的 ...

  8. HTML5 DOM扩展

    一.选择符 1. querySelector()方法:返回与该模式匹配的第一个元素 //取得body元素 var body = document.querySelector("body&qu ...

  9. 树莓派上搭建arduino开发环境

    -------------还是博客园上面的格式看这舒服,不去新浪了------------- 为什么要在树莓派上开发arduino呢?总要把树莓派用起来嘛,不然老吃灰. 树莓派使用SSH时没有图形界面 ...

  10. IOS编程学习笔记

    @interface -实例对象 +类名 #import "MyClass" @implementation MyClass -(id)initWithString:(NSStri ...