1.什么是webpack
先来看看官网的概念:
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle
可知webpack的核心概念在于两点:模块和打包
前端模块化:
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
模块化的好处:
- 避免命名冲突(减少命名空间污染)
- 更好的分离, 按需加载
- 更高复用性
- 高可维护性
webpack中的模块化
- 前端模块化的一些方案有:AMD、CMD、CommonJS、ES6等。
- 在ES6之前,我们要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发。并且在通过模块化开发完成了项目后,还需要处理模块间的各种依赖,并且将其进行整合打包。
- 而webpack其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系。而且不仅仅是JavaScript文件,我们的CSS、图片、json文件等等在webpack中都可以被当做模块来使用。这就是webpack中模块化的概念
打包
- 理解了webpack可以帮助我们进行模块化,并且处理模块间的各种复杂关系后,打包的概念就非常好理解了。
- 就是将webpack中的各种资源模块进行打包合并成一个或多个包(Bundle)。
- 并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作
2.webpack的配置
从 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念:
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
入口
入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。默认值为 ./src。
可以通过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)
//webpack.config.js
module.exports = {
entry: './path/to/my/entry/file.js'
};
出口
output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹。
可以通过在配置中指定一个 output 字段,来配置这些处理过程:
//webpack.config.js
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
3.loader
loader让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
在更高层面,在 webpack 的配置中 loader 有两个目标:
- test属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
- use属性,表示进行转换时,应该使用哪个 loader。
//webpack.config.js
const path = require('path');
const config = {
output: {
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
}
};
module.exports = config;
4.插件plugin
plugin是什么?
- plugin是插件的意思,通常是用于对某个现有的架构进行扩展。
- webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等。
loader和plugin区别
- loader主要用于转换某些类型的模块,它是一个转换器。
- plugin是插件,它是对webpack本身的扩展,是一个扩展器。
plugin的使用过程:
- 步骤一:通过npm安装需要使用的plugins(某些内置插件不需要安装)
- 步骤二:在webpack.config.js中的plugins中配置插件。
下面,我们就来看看可以通过哪些插件对现有的webpack打包过程进行扩容,让我们的webpack变得更加好用。
添加版权的Plugin
先来使用一个最简单的插件,为打包的文件添加版权声明该插件名字叫BannerPlugin,属于webpack自带的插件。
const path = require('path')
const webpack = require('webpack')
module.exports = {
...
plugins: [
new webpack.BannerPlugin('最终版权归XXX所有')
]
}
打包html的plugin
目前,我们的index.html文件是存放在项目的根目录下的。在真实发布项目时,发布的是dist文件夹中的内容,但是dist文件夹中如果没有index.html文件,那么打包的js等文件也就没有意义了。
所以,我们需要使用HtmlWebpackPlugin插件将index.html文件打包到dist文件夹中
HtmlWebpackPlugin插件可以为我们做这些事情:
- 自动生成一个index.html文件(可以指定模板来生成)
- 将打包的js文件,自动通过script标签插入到body中
plugins: [
new webpack.BannerPlugin('最终版权归coderwhy所有'),
new htmlWebpackPlugin({
template: 'index.html'
}),
]
压缩js的plugin
在项目发布之前,我们必然需要对js等文件进行压缩处理,我们使用一个第三方的插件uglifyjs-webpack-plugin
const path = require('path')
const webpack = require('webpack')
const uglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
...
plugins: [
new webpack.BannerPlugin('最终版权归coderwhy所有')
new uglifyJsPlugin()
]
}
模块热更新
搭建完本地服务后固然非常好用,但是它还是存在一个弊端:当只有一部分代码发生变化时,我们去刷新了整个页面。很明显,如果我们能在修改完代码后只刷新修改的部分,那么界面的更新效率会更高。
如何能做到呢?使用HotModuleReplacementPlugin插件即可。该插件是一个webpack内置的插件,并不需要安装,直接使用即可
webpack打包优化
关于优化贴几个文章参考一下:
https://juejin.im/post/6844903619158867982#heading-11
https://www.jianshu.com/p/481e7214a134
https://zhuanlan.zhihu.com/p/146189634