<webpack>webpack总结

原理


  • 代码转换:typeScript编译成JavaScriptscss,less编译成css
  • 文件优化:压缩JavaScripthtmlcss文件,压缩合并图片等
  • 代码分割:提供多个页面的公共代码,抽离首屏不需要的代码使其异步加载
  • 模块合并:模块化的项目里会有很多模块和文件,构建狗能把模块分类合并
  • 自动刷新:监听本地源代码,自动重构刷新浏览器
  • 扩展性好,插件机制完善

打包过程


  1. 利用babel完成代码转换,生成单个文件依赖
  2. 从入口开始分析,生成依赖图谱
  3. 将引用模块打包为立即执行函数
  4. 把最终的bundle文件写入bundle.js里

四大核心


  • entry:入口,即js入口源文件
  • output:生成文件
  • loader:文件处理
  • plugins:插件

Entry

webpack应该用哪个模块作为入口文件,作为构建内部依赖图的开始,进入入口后,webpack会找到哪些库和模块是入口依赖的,并随即被处理,最后输出到bundle.js的文件中

//单入口:entry是一个字符串
module.exports = {
  entry: './src/index.js'
}
//多入口:entry是一个对象
module.exports = {
  entry: './src/index.js'
}

Output


告诉webpack在哪输出bundles,以及怎么命名他,在配置文件中均可搞定

//单入口配置项
module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js’,
        path: __dirname + '/dist'
    }
};
//多入口配置项
module.exports = {
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',//[name]占位符确保文件名唯一
    path: __dirname + '/dist'
  }
}

Loader


loader让webpack能够处理非javaScript文件,因为webpack自己只能看懂javaScriptloader能够把所有类型的文件转换成webpack能够处理的模块,然后利用打包能力对他进行处理

Loader的特点

  • 每一个loader的职责都是单一的,只能完成一种转换
  • loader本质上是node.js模块,这个模块需要导出一个函数
  • loader总是从右到左被调用

常用Loader

处理样式
  • css-loader加载css文件
  • style-loader使用style标签把css-loader内部样式注入到html中
  • less-loader,sass-loader解析css预处理器
处理js

让我们能够使用最新的js代码(ES6,ES7等)及让我们能够使用基于js进行了拓展的语言,比如JSX等

处理文件

通常使用的两种loader是file-loaderurl-loader,两者主要的区别是url-loader能够设置图片的大小限制,如果大小超过限制,则行为等同于file-loader,如果图片大小不超过限制,那么图片会以base64的形式打包

处理vue单文件

vue-loader是webpack的加载器魔铠,它让我们的随心所欲的编写.vue格式的单文件组件。vue-loader 模块允许 webpack 使用单独的加载器模块(例如 sass 或 scss 加载器)提取和处理每个部分。该设置使我们可以使用 .vue 文件无缝编写程序。

在文章最后,我们会尝试开发一个简易的loader来加深我们的理解

Plugin


专注于处理webpack在编译过程里某个特定任务的功能模块

特点

  • 是一个独立的模块

  • 模块对外暴露一个js函数

  • 函数的原型 (prototype) 上定义了一个注入 compiler 对象的 apply方法 apply 函数中需要有通过 compiler 对象挂载的 webpack 事件钩子,钩子的回调中能拿到当前编译的 compilation 对象,如果是异步编译插件的话可以拿到回调 callback

  • 完成自定义自编程流程并处理complition对象的内部数据

  • 如果异步编译插件的话,数据处理完成后执行callback回调

常用Plugin

  • HotModuleReplacementPlugin 代码热替换。因为 Hot-Module-Replacement 的热更新是依赖于 webpack-dev-server,后者是在打包文件改变时更新打包文件或者 reload 刷新整个页面,HRM 是只更新修改的部分。
  • HtmlWebpackPlugin, 生成 html 文件。将 webpack 中entry配置的相关入口 chunk 和 extract-text-webpack-plugin抽取的 css 样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个 html 文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body中。
  • ExtractTextPlugin, 将 css 成生文件,而非内联 。该插件的主要是为了抽离 css 样式,防止将样式打包在 js 中引起页面样式加载错乱的现象。
  • NoErrorsPlugin报错但不退出 webpack 进程
  • UglifyJsPlugin,代码丑化,开发过程中不建议打开。 uglifyJsPlugin 用来对 js 文件进行压缩,从而减小 js 文件的大小,加速 load 速度。uglifyJsPlugin 会拖慢 webpack 的编译速度,所有建议在开发简单将其关闭,部署的时候再将其打开。多个 html 共用一个 js 文件(chunk),可用 CommonsChunkPlugin
  • purifycss-webpack 。打包编译时,可剔除页面和 js 中未被使用的 css,这样使用第三方的类库时,只加载被使用的类,大大减小 css 体积
  • optimize-css-assets-webpack-plugin 压缩 css,优化 css 结构,利于网页加载和渲染
  • webpack-parallel-uglify-plugin 可以并行运行 UglifyJS 插件,这可以有效减少构建时间

同样的,文章最后我们也会尝试开发一个Plugin

webpack配置


1、Webpack 项目初始化

1、新建 Web 项目

新建一个目录,再进入项目根目录执行 npm init 来初始化最简单的采用了模块化开发的项目;最终生成 package.json 文件;

$ npm init
复制代码

2、安装 Webpack 到本项目

(1)查看 Webpack 版本

运行以下命令可以查看 Webpack 的版本号

$ npm view webpack versions
复制代码

(2)安装 Webpack

可以选择(1)步骤罗列得到的 Webpack 版本号,也可以安装最新稳定版、最新体验版本,相关命令如下所示,我选择安装 4.28.2 版本(没有为什么,就想装个 4.x 的版本);

// 安装指定版本
npm i -D webpack@4.28.2

// 安装最新稳定版
npm i -D webpack

// 安装最新体验版本
npm i -D webpack@beta
复制代码

(3)安装 Webpack 脚手架

需要安装 Webpack 脚手架,才能在命令窗口执行 Webpack 命令,运行以下命令安装 Webpack 脚手架;

$ npm i -D webpack-cli
复制代码

3、使用 Webpack

使用 Webpack 构建一个采用 CommonJS 模块化编写的项目;

(1)新建页面入口文件 index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Webpack</title>
</head>
<body>
<!--导入 Webpack 输出的 JavaScript 文件-->
<script src="./dist/bundle.js"></script>  
</body>
</html>
复制代码

(2)新建需要用到的 JS 文件

show.js 文件

// 操作 DOM 元素,把 content 显示到网页上
function show(content) {
  window.document.getElementById('app').innerText = 'Hello,' + content;
}

// 通过 CommonJS 规范导出 show 函数
module.exports = show;
复制代码

main.js 文件

// 通过 CommonJS 规范导入 show 函数
const show = require('./show.js');
// 执行 show 函数
show('Webpack');
复制代码

(3)新建 Webpack 配置文件 webpack.config.js

const path = require('path');

module.exports = {
  // JavaScript 执行入口文件
  entry: './main.js',
  output: {
    // 把所有依赖的模块合并输出到一个 bundle.js 文件
    filename: 'bundle.js',
    // 输出文件都放到 dist 目录下
    path: path.resolve(__dirname, './dist'),
  }
};
复制代码

(4)执行 webpack 命令进行构建

在 package.json 文件中配置编译命令,如下所示:

  "scripts": {
    "build": "webpack --config webpack.config.js",
  },
复制代码

执行以下命令进行项目的 Webpack 编译,成功后会在项目根目录下生成编译目录 dist ;

$ npm run build
复制代码

(5)运行 index.html

编译成功后,我们用浏览器打开 index.html 文件,能看到页面成功显示 “Hello Webpack”;

2、Loader 配置

本节通过为之前的例子添加样式,来尝试使用 Loader;

(1)新建样式文件 main.css

#app{
  text-align: center;
  color:'#999';
}
复制代码

(2)将 main.css 文件引入入口文件 main.js 中,如下所示:

// 通过 CommonJS 规范导入 CSS 模块
require('./main.css');

// 通过 CommonJS 规范导入 show 函数
const show = require('./show.js');
// 执行 show 函数
show('Webpack');
复制代码

(3)Loader 配置

以上修改后去执行 Webpack 构建是会报错的,因为 Webpack 不原生支持解析 CSS 文件。要支持非 JavaScript 类型的文件,需要使用 Webpack 的 Loader 机制;

(3.1)运行以下命令,安装 style-loader 和 css-loader,其中:

  • css-loader 用于读取 CSS 文件;
  • style-loader 把 CSS 内容注入到 JavaScript 中;
$ npm i -D style-loader css-loader
复制代码

(3.2)进行以下配置

module:{
rules:[
  {
	// 用正则去匹配要用该 loader 转换的 CSS 文件
	test:/\.css$/,
	use:['style-loader','css-loader']
  }
 ]
}
复制代码

(4)查看结果

编译后,刷新 index.html ,查看刚刚的样式 loader 已经起作用;

1

3、Plugin 配置

(1)安装样式提取插件 extract-text-webpack-plugin

$ npm i -D extract-text-webpack-plugin@next
复制代码

(2)plugin 文件配置如下

  module:{
    rules:[
      {
        // 用正则去匹配要用该 loader 转换的 CSS 文件
        test:/\.css$/,
        use:ExtractTextPlugin.extract({
          use:['css-loader']
        }),
      }
    ]
  },
  plugins:[
    new ExtractTextPlugin({
       // 从 .js 文件中提取出来的 .css 文件的名称
       filename:`[name]_[hash:8].css`
    }),
  ]
复制代码

(3)查看结果

通过以上配置后,执行 Webapack 的执行命令,发现在 dist 目录下,生成对应的 css 文件;存在的坑点:

  • 我们需要手动将生成的 css 文件引入到 index.html 中;
  • 修改 css 文件后,会生成新的 css 文件,原先的不会删除;

4、使用 DevServer

(1)执行以下命令安装 webpack-dev-server

$ npm i -D  webpack-dev-server
复制代码

在 package.json 中配置启动命令

  "scripts": {
    "build": "webpack --config webpack.config.js",
    "dev": "webpack-dev-server",
  },
复制代码

运行命令后,就可以启动 HTTP 服务

$ npm run dev
复制代码

启动结果如下所示,我们可以通过 http://localhost:8080/ 访问我们的 index.html 的demo

1

(2)实时预览

我们在运行命令后面添加参数 --watch 实现实时预览,配置如下所示:

  "scripts": {
    "dev": "webpack-dev-server --watch"
  },
复制代码

然后我们修改 main.js 的传入参数,发现并不能实时预览,也没有报错!!! why?

踩坑:

在 index.html 中需要将 js 的路径修改为:

<script src="bundle.js"></script>  
复制代码

而不能是之前的(因为这个是编译生成的,并不是通过 devServer 生成放在内存的)

<script src="./dist/bundle.js"></script> 
复制代码

(3)模块热替换

可以通过配置 – hot 进行模块热替换;

番外


没错,文章最后了,现在我们开始开发一个loaderplugin

开发一个loader

需求:开发一个loader,将KobeBryant转换为mamba forever`。

1.编写loader

新建目录my-loader作为名字,执行npm init -y快速创建一个模块化项目,然后新建index.js

module.exports = function(content) {
	return content && content.replace(/KobeBryant/gi , 'mamba forever')
}
2.注册模块

一般情况下,我们需要的loader都是利用npm安装,但是我们可以使用npm link命令,以求在不发布模块的情况下,将本地的源码链接到项目的node_modules下。在项目的根目录下执行以下命令

λ npm link my-loader
3.在webpack中配置loader

webpack.base.config.js中加上以下配置

{
	test:/\.js/,
	loader:'my-loader'
}

这样我们js里所有的字符串KobeBryant就会替换为mamba forever

4.配置参数

前面我们是写死的替换,如果我们想要通过配置项来进行改变怎么办

// index.js
var utils = require('loader-utils')
module.exports = function (content) {
    const options = utils.getOptions(this)
    return content && content.replace(/KobeBryant/gi , options.name)
}

// webpack.base.conf.js
{
  test:/\.js/,
  use: {
    loader: 'my-loader',
    options: {
      name: 'KobeBryant',
    }
  }
}

开发一个Plugin

  • webpack在编译中,会广播很多事件
  • webpack应用了观察者模式,插件可以监听webpack事件来触发对应的处理逻辑
  • 插件中可以使用webpack的api
1.编写插件

创建目录my-plugin作为编写的插件,执行npm init -y快速创建一个模块化项目,然后新建index.js

class MyPlugin {
	constructor(doneCakkback , failCallback) {
		//保存在创建实例时候传入的回调函数
        this.doneCallback = doneCallback
        this.failCallback = failCallback
	}
    
    apply(compiler) {
        //成功完成一次完整的编译和输出时,会触发done
        compile.plugin('done' , stats => {
            this.doneCallback(stats)
        })
        
        //出现异常的时候,触发fail
        compiler.plugin('fail' , err => {
            this.failCallback(err)
        })
    }
}

module.exports = MyPlugin
2.注册模块

同样的,我们link一下,以便于我们能直接使用本地的模块

λ npm link my-plugin
3.配置插件

webpack.base.conf.js加上以下配置

plugins: [
	new MyPlugin(
    	stats => {
            console.log('编译成功')
        },
        err => {
        	console.error('编译失败')
        }
    )
]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值