一.认识webpack
官网解释:从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具。
从模块化和打包两个角度来理解:
模块化:
webpack其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系,而且不仅仅是JavaScript文件,CSS、图片、json文件等等在webpack中都可以被当做模块来使用
打包:
合并成一个或多个包(Bundle),并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。
静态:
这样表述的原因是我们最终可以将代码打包成最终的静态资源(部署到静态服务器);
webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能
webpack如何打包?
- 在webpack开始打包时,会根据命令或者配置文件找到入口文件
- 从入口开始,根据文件中之间的依赖关系生成依赖关系图,这个依赖关系图会包括项目中所需要的所有模块,包括 js文件,css文件,图片,字体等
- 依次遍历图结构,根据文件类型使用对应的loader进行解析,依次进行打包
二.webpack的安装
- 安装webpack首先需要安装Node.js,Node.js自带了软件包管理工具npm
- 全局安装webpack(这里我先指定版本号3.6.0,因为vue cli2依赖该版本)
npm i [email protected] -g
- 局部安装webpack(后续才需要)
--save-dev`是开发时依赖,项目打包后不需要继续使用的。
cd 对应目录
npm i [email protected] --save-dev
- 为什么全局安装后,还需要局部安装呢?
- 在终端直接执行webpack命令,使用的全局安装的webpack
- 当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部webpack
要同时安装webpack,webpack-cli(此工具用于在命令行中运行 webpack)
npm install webpack webpack-cli –g # 全局安装
npm install webpack webpack-cli –D # 局部安装
**那么它们是什么关系呢? **
- 在命令行执行webpack命令,会执行node_modules下的.bin目录下的webpack;
- webpack在执行时是依赖webpack-cli的,如果没有安装就会报错;
- 而webpack-cli中代码执行时,才是真正利用webpack进行编译和打包的过程;
- 所以在安装webpack时,我们需要同时安装webpack-cli(第三方的脚手架事实上是没有使用webpack-cli的,而是类似于自 己的vue-service-cli的东西)
三.webpack的起步
1.准备工作:
- dist文件夹:用于存放之后打包的文件
- src文件夹:用于存放我们写的源文件
main.js:项目的入口文件。具体内容查看下面详情。
mathUtils.js:定义了一些数学工具函数,可以在其他地方引用,并且使用。具体内容查看下面的详情。
index.html:浏览器打开展示的首页html
2.js文件的打包
现在的js文件中使用了模块化的方式进行开发,他们可以直接使用吗?不可以。
- 因为如果直接在index.html引入这两个js文件,浏览器并不识别其中的模块化代码。
- 另外,在真实项目中当有许多这样的js文件时,我们一个个引用非常麻烦,并且后期非常不方便对它们进行管理。
我们应该怎么做呢?使用webpack工具,对多个js文件进行打包。
- webpack是模块化的打包工具,所以它支持代码中写模块化,可以对模块化的代码进行处理。
- 如果在处理完所有模块之间的关系后,将多个js打包到一个js文件中,引入时就非常方便了。
如何打包?
1.webpack
直接执行webpack默认会将当前目录下的 src/index.js 作为入口文件,所以,如果当前项目中没有存在src/index.js文件,那么会报错,打包后的文件会保存在dist/main.js中
2.webpack --entry ./src/main.js --output-path ./dist指定入口文件和出口文件
将src/main.js文件打包,并把打包好的文件保存到dist/main.js中
3.使用打包后的文件
打包后会在dist文件下,生成一个main.js文件
main.js文件,是webpack处理了项目直接文件依赖后生成的一个js文件,我们只需要将这个js文件在index.html中引入即可
四.webpack的配置
1.webpack.config.js中配置入口文件和出口文件
注意:
- output中的path必须是绝对路径
- 使用node提供的核心模块path中的resolve方法对路径进行拼接
- __dirname是node提供的一个内置变量,用来获取当前文件所在的绝对路径
在命令行中执行 webpack命令时,会去webpack.config.js文件中找对应的入口文件和出口文件进行打包,但是在命令行中执行webpack使用的是全局安装的webpack,但是一个项目往往依赖特定的webpack版本,全局的版本可能很这个项目的webpack版本不一致,导出打包出现问题
2.局部安装webpack
2.1 npm init 初始化package.json包管理工具
2.2 下载局部webpack
--save-dev 开发时依赖,开发时需要的包,生产环境不要的包,对应的包信息保存在package.json文件中的devDependencies
3.package.json中定义启动
在package.json的scripts中定义自己的执行脚本。
"build":"webpack" ------当执行npm run build 的时候,执行webpack
package.json中的scripts的脚本在执行时,会按照一定的顺序寻找命令对应的位置。
首先,会寻找本地的node_modules/.bin路径中对应的命令。
如果没有找到,会去全局的环境变量中寻找。
4. npx webpack
在命令行中使用npx webpack 也是使用的局部webpack
五.loader 的使用
1.css 文件处理
项目开发过程中,我们需要添加很多的样式,而样式我们往往写到一个单独的文件中。
在src目录中,创建一个css文件,其中创建一个normal.css文件,将零散的css文件放在一个css文件夹中。
但是,这个时候normal.css中的样式会生效吗?
当然不会,因为我们压根就没有引用它。
webpack也不可能找到它,因为我们只有一个入口,webpack会从入口开始查找其他依赖的文件。
在入口文件中引用:
通过上述引用,运行npm run build,会报错,需要loader对css文件进行处理
2.为什么要使用loader?
主要是用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖。
但是,在开发中我们不仅仅有基本的js代码处理,我们也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等。对于webpack本身的能力来说,对于这些转化是不支持的。那怎么办呢?给webpack扩展对应的loader就可以啦。
3.loader 使用过程
步骤一:通过npm安装需要使用的loader
npm install css-loader --save-dev
npm install style-loader --save-dev
css-loader 负责加载css文件,对css文件进行解析,并不会将解析之后的css插入到页面中
**style-loader **style-loader 负责把css样式以<style>标签嵌入到文档中
步骤二:在webpack.config.js中的module关键字下进行配置
rules是一个数组,每一项都是一个配置对象
test:匹配以.css结尾的文件,对资源进行匹配,通常使用正则
ues:使用style-loader,css-loader进行处理
注意:style-loader需要放在css-loader的前面,这是因为webpack在读取使用的loader的过程中,是按照从右向左的顺序读取的(或者说从下到上,或者说从后到前的)。
module.rules中各配置项说明:
test:对资源进行匹配,通常使用正则
use:[{
loader:'css-loader', //必选属性,对应的值是字符串 options:{} //可选属性,值可以是对象或者字符串,值会被传入到loader中 }],
use:['css-loader'] //use的简写形式,当不需要配置项时
loader:'css-loader' //uses[{loader:'css-loader'}] 的语法糖
4.less文件处理
在main.js中引入.less文件
安装 less-loader
注意:这里还安装了less,因为webpack会使用less将less文件转化成css文件
修改对应的配置文件,添加一个rules选项,用于处理.less文件
5.图片处理
在项目中加入图片,在css样式中引用图片
处理图片文件,可以分别使用url-loader,file-loader,两者工作方式是相似的,但是url-loader可以将较小的文件,转成base64的URI
5.1 使用 file-loader
file-loader的作用就是帮助我们处理import/require()方式引入的一个文件资源,并且会将它放到我们输出的文件夹中
安装file-loader:
添加配置项:
再次打包,就会发现dist文件夹下多了一个图片文件:
我们发现webpack自动帮助我们生成一个非常长的名字,这是一个32位hash值,目的是防止名字重复,但是,真实开发中,我们可能对打包的图片名字有一定的要求
比如,将所有的图片放在一个文件夹中,跟上图片原来的名称,同时也要防止重复
所以,我们可以在options中添加上如下选项:
这个时候我们可以使用PlaceHolders来完成,webpack给我们提供了大量的PlaceHolders来显示不同的内容: https://webpack.js.org/loaders/file-loader/#placeholders
- img:文件要打包到的文件夹
- [name]:获取图片原来的名字,放在该位置
- [hash:8]:为了防止图片名称冲突,依然使用hash,但是我们只保留8位
- [ext]:使用图片原来的扩展名
但是,我们发现图片并没有显示出来,这是因为图片使用的路径不正确,默认情况下,webpack会将生成的路径直接返回给使用者
该路径是用在index.html,但是实际生成的图片文件位于dist/img/xx.jpg,所以这里我们需要在路径下再添加一个dist/
5.2 使用 url-loader
**url-loader 和 file-loader **的工作方式是相似的,但是可以将较小的文件,转成base64的URI
安装url-loader:
修改webpack.config.js文件:
limit 属性的作用:
- 当图片小于8kb时,对图片进行base64编码 ,当图片大于8kb,不会进行base64编码
- 如果不配置limit,默认会将所有图片都转换成base64格式,小图片转换成base64可以减少http请求次数,但是大图片也转换成base64会增加文件的大小,反而会影响页面的请求速度
6.ES6语法处理--babel
babel:Babel是一个工具链,主要用于旧浏览器或者环境中将ECMAScript 2015+代码转换为向后兼容版本的 JavaScript;
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
配置webpack.config.js文件:
Exclude:排除node_modules中的文件,只转换src中的文件
重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法
babel的底层原理:
babel是如何做到将我们的一段代码(ES6、TypeScript、React)转成另外一段代码(ES5)的呢?
- 从一种源代码(原生语言)转换成另一种源代码(目标语言),这是什么的工作呢?
- 就是编译器,事实上我们可以将babel看成就是一个编译器。
- Babel编译器的作用就是将我们的源代码,转换成浏览器可以直接识别的另外一段源代码;
**Babel也拥有编译器的工作流程: **
- 解析阶段(Parsing)
- 转换阶段(Transformation)
- 生成阶段(Code Generation)
七.plugin的使用
webpack另一个核心是插件,官方对插件的描述:
- Loader是用于特定的模块类型进行转换;
- Plugin可以用于执行更加广泛的任务,比如打包优化、资源管理、环境变量注入等,是对webpack现有功能的各种扩展。
7.1 CleanWebpackPlugin
作用:每次打包时,自动删除上一次打包的dist文件夹
下载:npm i clean-webpack-plugin -D
配置:
7.2 HTMLWebpackPlugin
作用:打包生成的dist文件夹中并且有index.html文件,但是在进行项目部署的时候也是需要入口文件的,HTMLWebpackPlugin插件可以帮助我们对index.html文件进行打包,并且在打包的index.html中引用main.js
下载:npm i html-webpack-plugin -D
配置:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
plugins: [
new HtmlWebpackPlugin({
title: "webpack title"
}),
]
}
index.html个文件是如何生成的呢?
- 默认情况下是根据ejs的一个模板来生成的;
- 在html-webpack-plugin的源码中,有一个default_index.ejs模块;
如果要自定义index.html文件的内容?
在配置HtmlWebpackPlugin时,我们可以添加如下配置:
- template:指定我们要使用的模块所在的路径;根据这个模板生成index.html
- title:在进行htmlWebpackPlugin.options.title读取时,就会读到该信息;
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
plugins: [
new HtmlWebpackPlugin({
// 可以通过全局变量htmlWebpackPlugin.options.title读取
title: "webpack title",
template: "./public/index.html"
}),
]
}
7.3 CopyWebpackPlugin
作用:将资源复制到打包之后的文件夹中
下载:npm i copy-webpack-plugin
配置:
const CopyWebpackPlugin = require('copy-webpack-plugin');
export default {
plugins:[
new CopyWebpackPlugin({
patterns: [
{
from: "public",
to: "./",
globOptions: {
ignore: [
// 必须要加上**/ 表示public文件夹下的/index.html
"**/index.html"
]
}
}
]
})
]
}
复制的规则在patterns中设置:
- from:设置从哪一个源中开始复制;
- to:复制到的位置,可以省略,会默认复制到打包的目录下;
- globOptions:设置一些额外的选项,其中可以编写需要忽略的文件:
7.4 DefinePlugin
作用:在编译时创建配置的全局常量,是一个webpack内置的插件(不需要单独安装):
const { DefinePlugin } = require('webpack');
module.export = {
plugins: [
new DefinePlugin({
// 赋值时是取字符串内部的内容,所以需要包裹两层引号
BASE_URL: '"./"'
}),
]
}
八.mode配置
Mode配置选项,可以告知webpack使用响应模式的内置优化:
- 默认值是production(什么都不设置的情况下);
- 可选值有:'none' | 'development' | 'production';
这几个选项有什么样的区别呢?
八.搭建本地服务器
版权归原作者 ICanWin_lll 所有, 如有侵权,请联系我们删除。