本文是我在学习过程中记录学习的点点滴滴,目的是为了学完之后巩固一下顺便也和大家分享一下,日后忘记了也可以方便快速的复习。
webpack 与常用插件结合使用实战
前言
前面讲过 webpack 本身只能对 js 文件进行打包(即只能把引入js 文件转换成浏览器能够识别的文件),如果要对其他类型文件(比如 CSS、image 等)进行作为模块引入,就需要结合第三方插件来使用。这些插件在 Webpack 中被称为 Loader (加载器)。Loader可以理解为其他类型文件(比如 CSS、image 等文件)的转换器,它实质是一个函数,参数就是要转换的源文件(比如 CSS、image等文件),返回值就是转换后的浏览器能够识别的文件。因此可以通过 require 或 import 来导入加载任何类型的模块文件,比如 CSS、图片,然后通过 webpack 结合各种 Loader(加载器)就能解析识别。
一、使用 webpack 结合插件打包 css 资源
总结:
我们的css文件要和之前讲过的js文件一样要经过打包后浏览器才能识别,所以我们要使用打包工具打包。
我们的css文件需要打包需要先经过css-loader插件处理 css 中导入的外部 css 资源(css可能会导入其他的外部资源使用)。
然后使用style-loader插件把外部解析出来的样式插入到 DOM 中,即在html的head 中插入一个 style 标签,并把样式写入到这个标签里。
这些打包的css文件打包到哪里和打包规则都在webpack.config.js中配置。
参考官网:
https://www.webpackjs.com/guides/asset-management/
1.1、搭建项目框架
|-index.html——主页文件【单页面应用唯一的 html 文件】
|-src——存放源文件(项目核心文件)文件夹
|-main.js——入口文件,其他的相关(js)模块文件都是通过它层层引 入
|-webpack.config.js—webpack 的配置文件,必须放在项目的根目录下
|-package.json——前面初始化项目时已产生(整个项目配置文件)
为了从 JavaScript 模块中 import 一个 CSS 文件,你需要
在 module 配置中 安装并添加 style-loader 和 css-loader
1.1.1、安装并添加 style-loader 和 css-loader 插件
npm install --save-dev style-loader css-loader
CSS 代 码 会 先 被 css-loader 处 理 一 次 , 然 后 再 交
给 style-loader 进行处理。
那么这两步分别是做什么呢?
1、css-loader 的作用是处理 css 中导入的外部 css 资源,比如(import ‘./css/mystyle.css’),即把外部 css 文件中的样式解析出来。
2、style-loader 的作用是把外部解析出来的样式插入到 DOM 中,方法是在 head 中插入一个 style 标签,并把样式写入到这个标签里。
上面的--save-dev 是开发环境依赖 ,安装完成之后,在 package.json文件中就可以看到有这 2 个依赖 。( 在 devdependencies:下面)
1.2、配置 webpack.config.js 文件
const path = require("path");
module.exports = {
mode: 'development',
//入口
entry: './src/main.js',// 入口模块文件路径
output: {
path: path.join(__dirname, './dist'), filename: 'bundle.js'
},
module: {
rules: [ //配置 css 转 js 的规则
{
test: /\.css$/,//正则表达式,\.取消.的元字符含义,$表示结尾,即匹配扩展名为 css 文件,两端都要加/
use: [ //下面 2 个加载器的顺序不能反
'style-loader', 'css-loader']
}
]
}
}
1.3、测试
(1)在项目的 src 文件夹下新建一个文件夹 css,下面添加一个style.css 文件,并输入一个测试样式:
body{
background-color: azure;
}
(2)下面在入口文件 main.js 文件中以模块化形式引入
style.css 文件,把 main.js 原有内容先全部删除。
//将样式文件 style.css 以模块化【style.css 作为一个模块】引入到该位置
import ‘./css/style.css’
(3)打包,即在终端输入……webpack-demo1> npm run start执行之后,如下图所示,就是告诉我们已经把 main.js 和 style.css 一起打包了,这里打包的流程再说下:结合 package.json 和webpack.config.js 两个文件我们知道打包的入口文件是 main.js,但是 main.js 中通过模块化形式引入了 style.css,然后我们又配置了css 加载器,能够识别 css 文件,因此就能够把它一起打包到输出文件[dist/bundle.js]。如果事先没有安装 css 加载器(css-loader,style-loader)将不能把样式文件 style.css 一起打包的。我们打开打包输出后的文件 bundle.js,我们不太认识,但是浏览器认识,我们可以通过 ctrl+f 查询下我们所写代码的踪迹(比如查找 background)。如下图所示,这些就是浏览器能够识别的 css 模块化代码。
接下来我们就在浏览器中打开 index.html 文件,看到了我们通过 css 样式设置的背景颜色,如下图所示。同时我们通过查看器查看源代码发现 css 样式文件的内容被加载进来了
二、使用 webpack 结合插件打包 image 资源
总结:
这里是要打包一些列的不同格式的图片,使用file-loader进行打包,也在webpack.config.js 文件配置打包规则和打包路径,打包成功后会在目标路径(/dist)也复制出一张一样的图片,并且在 bundle.js 文件中也可以看到该背景图片的踪迹。
但是在html中要引用的话必须要和图片在同一目录下,所以这里暂时将html复制一份到dist里面,下面会将会讲解其他更好的处理方法。
假想,现在我们正在下载 CSS,但是 CSS 中用到的背景和图标这些图片,要如何处理呢?
使用 file-loader,我们可以轻松地将这些内容混合到 CSS 中
2.1、安装 file-loader
npm install --save-dev file-loader
2.2、配置 webpack.config.js 文件
//引用 node.js 中的 path 模块,用来处理文件路径
const path = require("path");
module: {
rules: [ //配置 css 转 js 的规则
{
test: /\.css$/,//正则表达式,匹配以 css 结尾文件,不要用引号引住
use: [ //下面 2 个加载器的顺序不能反
'style-loader',//让 javascript 识别转换后的 js(css)
'css-loader' //css 转为 js
]
}, {
test: /\.(png|svg|jpg|gif)$/, // svg 是一种矢量图
use: [
'file-loader']
}
]
}
2.3、测试
(1)先找一个图片 bg.jpg 放入到 css 文件夹下。
(2)修改下 style.css 文件,增加一个背景图片。按住 ctrl 键,单击下图片名称处(bg.jpg)能够把图片显示出来说明路径没问题
body{
background-color: azure;
background-image: url(./bg.jpg);
}
(3)保存下,重新打包。终端输入
……webpack-demo1> npm run start
打包输出之后最明显的是看到了把原来的图片 bg.jpg 复制到了输出目录 dist 下,并且重新命名了,因为不重新命名容易导致名称冲突。当然在输出文件 bundle.js 文件中也可以看到该背景图片的踪迹的。
(4)浏览 index.html 文件看效果:发现背景图片没有出来,原因是什么呢?通过源代码可以看到图片已经引入,但是路径不对(是相对引入),直接如下图写法是表示 index.html 文件与那个图片文件在同一个目录下,但是实际上当前的 index.html 文件是在项目的根目录下,而那个图片文件是在 dist 文件夹下,所以图片显示不出来。
解决方案:
(1)把打包生成的图片移到与 index.html 相同的位置。效果出来没问题,但是这样做非常不好,打包后的文件不应该移出去,而且后续项目要发布,我们是发布 dist 这个目录就可以的,如果移出去了就会变得麻烦。因此,把图片移回去。
(2)把 index.html 复制一份到 dist 目录下。但是这个 时候
index.htm 中对 bundle.js 的引用路径就要修改下。
<script src=“./dist/bundle.js”></script>
改为:
<script src=“./bundle.js”></script>
这个时候要浏览看效果就是浏览 dist 目录下的 index.html。发现效果 OK。
三、使用 webpack 配合 HtmlWebpackPlugin 插件解决文件路径
总结:
安装HtmlWebpackPlugin 插件,然后再在webpack.config.js 文件引入插件和配置插件信息就可以实现自动复制html到dist目录下并自动引用输出文件。
引出问题:
上面存在的问题:
(1)手动把 index.html 复制一份到 dist 目录下
(2)手动修改了输出文件 bundle.js 的引用路径
(3)而且如果该输出文件名假设在 webpack.config.js 里修改过了,那么这个文件名也得修改。那么有没有不需要手动操作的,就会自动复制一份 index.html到输出目录下,并且会自动引用输出文件(webpack.config.js 里配置好的输出文件名)呢?
——借助 HtmlWebpackPlugin 插件。
3.1、HtmlWebpackPlugin 插件作用
(1)将 index.html 打包到输出文件(bundle.js)所在目录中
(2)会在 index.html 中自动的 通过<script> 引入输出文件
(bundle.js)
3.2、安装 HtmlWebpackPlugin 插件
打开要安装的目录然后打开cmd窗口输入:
npm install --save-dev html-webpack-plugin
3.3、配置 webpack.config.js 文件
增加的代码如下 2 处黄色底纹代码,然后保存。
//引用 node.js 中的 path 模块,用来处理文件路径
const path = require(“path”);
//引入插件 html-webpack-plugin
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
// 导出一个 webpack 具有特殊属性配置的对象
// 安装下 Node Snippets 插件,输入 module 会有智能提示
module.exports = {
mode: ‘development’,//指定打包为生产环境、开发环境或者设置
none
//入口
entry: ‘./src/main.js’,// 入口模块文件路径
//出口对象
output: {
// path 必须是一个绝对路径 , __dirname 是当前配置文件webpack.config.js 的绝对路径。然后与输出目录 dist 拼接成一个决 路径
path: path.join(__dirname, ‘./dist’), filename: ‘bundle.js’
},// 配置插件
plugins: [
new HtmlWebpackPlugin({
//指定要打包的模板页面 index.html,采用的是相对路径,与当前配置文件在同级目录,所以为./。就会找到把 index.html 文 件并把 它打包到与输出文件 bundle.js 的同级目录下
template: ‘./index.html’
})
],module: {
rules: [ //配置 css 转 js 的规则
{
test: /.css$/,//正则表达式,匹配以 css 结尾文件
use: [ //下面 2 个加载器的顺序不能反
‘style-loader’,//让 javascript 识别转换后的 js(css)
‘css-loader’ //css 转为 js
]
}, {
test: /.(png|svg|jpg|gif)$/, use: [
‘file-loader’]
}
]
}
}
3.4、测试效果
(1)为了更好的测试效果,先把原来的整个 dist 目录删除。
作为入口即可),就是因为打包时会自动在index.html 文件中引入我们打包输出后的文件(bundle.js),并放到dist 目录下。最终我们只要发布 dist 目录即可。
(2)index.html 文件中原来对 bundle.js 引入语句删除,因为打包后会自动引入。
(3)保存下,重新打包。终端输入
……webpack-demo1> npmrun start
打包之后查看下打包后的 index.html 文件,它是在原来的
index.html 基础上增加一条对输出文件的引用语句。如下:
<script type=“text/javascript” src=“bundle.js”></script>
最终预览就是预览 dist 目录下的 index.html。
从这里我们发现根目录下的 index.html 文件里实际什么都没写哦(在后面单页面开发中也只需要在 index.html 中加入
至此,感觉比较完美,但是还不够,请继续往下学习。
四、使用 webpack 配合 webpack-dev-server 插件实现自动打包和刷新页面
总结:
以前使用watch可以实现自动打包,但是还不能实现自动刷新,这里使用webpack-dev-server 可以实现自动刷新。也要先安装,然后再在webpack.config.js中配置devServer实现实时加载。
还要package.json 文件配置映射命令来实现自动打开浏览器在服务器上访问我们上面的文件实时刷新。
修改完js文件后直接运行npm run dev他就会自动打包自动打开浏览器刷新页面。
引出问题:
上面每次修改都需要重新打包,打包后还要重新刷新浏览
器。虽然在 package.json 文件中映射了"webpack --watch"的别名,能做到自动监视修改,并在修改后自动重新编译,但是在浏览器还是需要我们手动刷新。
“watch”: “webpack --watch” 那么有没有更自动的方法呢?就是修改后无需手动重新打包,也无需刷新浏览器,而是自动更新刷新浏览器。
【参考官网】开发——使用 webpack-dev-server
4.1、webpack-dev-server 作用
采用 webpack 提供的工具:webpack-dev-server ,它提供
了一个简单的 web 服务器,在运行时更新所有类型的模块后,而无需手动打包和刷新页面,会自动打包和刷新页面。可以很大程度提高开发效率。
4.2、安装 webpack-dev-server
打开要安装的目录然后打开cmd窗口输入:
npm install --save-dev webpack-dev-server
4.3、配置 webpack.config.js
修改配置文件,告诉开发服务器(dev server),在哪里查找文件,添加的内容如下黄色底纹所示:
//引用 node.js 中的 path 模块,用来处理文件路径
const path = require(“path”);
//引入插件 html-webpack-plugin
const HtmlWebpackPlugin = require(‘html-webpack-plugin’);
// 导出一个 webpack 具有特殊属性配置的对象
// 安装下 Node Snippets 插件,输入 module 会有智能提示
module.exports = {
mode: ‘development’,//指定打包为生产环境、开发环境或者设置none
//入口
entry: ‘./src/main.js’,// 入口模块文件路径
//出口对象
output: {
// path 必须是一个绝对路径 , __dirname 是当前配置文件
webpack.config.js 的绝对路径。然后与输出目录 dist 拼接成一个决定路径
path: path.join(__dirname, ‘./dist’), filename: ‘bundle.js’ },// 配置插件
plugins: [
new HtmlWebpackPlugin({
//指定要打包的模板页面 index.html,采用的是相对路径,与当前配置文件在同级目录,所以为./。就会找到把 index.html 文件并把它打包到与输出文件 bundle.js 的同级目录下
template: ‘./index.html’ })
],//实时重新加载
devServer: {
//在当前目录的 dist 目录下查找文件
contentBase: ‘./dist’ },
module: {
rules: [ //配置 css 转 js 的规则
{
test: /.css$/,//正则表达式,匹配以 css 结尾文件
use: [ //下面 2 个加载器的顺序不能反
‘style-loader’,//让 javascript 识别转换后的 js(css)
‘css-loader’ //css 转为 js
]
},{
test: /.(png|svg|jpg|gif)$/, use: [
‘file-loader’ ]
}
]
}
}
以上配置也就是告知 webpack-dev-server,在 localhost:8080【默认端口】下建立服务,将 dist 目录下的文件,作为可访问文件。
4.4、修改 package.json 文件
添加一个 script 脚本,可以直接运行开发服务器(dev server):
"webpack-dev-server --open"运行 webpack-dev-server 服务,打开浏览器。
{ “name”: “webpack-demo1”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”,
“scripts”: {
“showVersion”: “webpack -v”,
“start”: “webpack”,
“watch”: “webpack --watch”,
“dev”: “webpack-dev-server --open”
},
以上默认是通过 8080 端口进入,如果端口冲突会选择下一个,如果自己想指定端口可以如下修改:【port 后有一个空格】
“dev”: “webpack-dev-server --open --port 8000”
4.5、测试效果
在命令行中运行 npm run dev,就会看到浏览器自动加载页面,如下图所示,可以看到是作为一个服务在运行,当然运行的是 dist目录下的 index.html 文件(不信,可以在端口号后面加上/index.html)。如果现在修改任意源文件,比如把 style.css 中设置背景图片的样式注释掉,然后保存下,就会看到会自动重新编译,编译之后,浏览器就重新刷新了!
五、使用 webpack 配合 babel 解决浏览器的兼容性
问题:vue 开发中经常会使用 ES6 新语法(箭头函数、const、解构赋值等),但是一些低版浏览器不支持,比如 IE7 等。当然如果不考虑浏览器的兼容性问题,可以不学习本节内容。
使用参考官网:
https://webpack.docschina.org/loaders/babel-loader/
5.1、 安装 babel-loader 等相关插件
npm install -D babel-loader @babel/core @babel/preset-env webpack
说明:最后一个 webpack 已经安装过了,不用安装了。
5.2、配置 webpack.config.js 文件
添加以下黄色底纹代码。
{//解决兼容性问题
test: /.m?js$/, exclude: /(node_modules)/,//排除 node_modules【是各种插件安装目录】下的代码不用babel_loader 去转换
use: {
loader: ‘babel-loader’, options: {
presets: [‘@babel/preset-env’]//babel 中内置的转换规则工具,刚才配套一起安装的就还有这个。
}
}
}