Webpack
我们平时写好的前端代码要部署到服务器上进行测试,这个时候就需要打包工具,这就是webpack。Webpack 是一个前端资源加载/打包工具
。
那为什么要打包呢??????
因为我们平时开发的代码是我们自己写的,同时也具有可观性,这是开发环境。但是如果要运行它,那么可观不可观就完全不重要了,重要的只有速度,因此需要用webpack将开发环境代码转换成运行环境代码从而提升运行速度。
webpack就是要找出代码模块之间的依赖关系,按照一定的规则把这些模块组织合并为一个JavaScript文件。
但是将所有的模块全部合并到一个JS文件里面,这个JS文件将会非常庞大,因此我们就需要利用一些规则来打破这种局限。
快速入门
1、安装Node
首先需要了解webpack的安装与使用,webpack依赖于Nodejs,因此需要安装node在电脑上才可以使用webpack。
2、安装webpack-cli
webpack-cli是命令行工具包,也是一种脚手架,简单来说,我们要在命令行里面使用webpack就需要webpack-cli。
3、安装webpack
webpack是webpack核心包
需要处理的问题
举个🌰:
在我们编写的代码中,假如就在一个Vue项目里面,我们会有很多很多的文件,js/Vue,我们还会应用比较方便的ES6语法来编写,然后以模块化的方式导入导出来引用,但是实际上我们的项目最最开始的构建页面的HTML文件是index.HTML文件,但是在HTML文件里面引用模块化概念会报错。
所以利用webpack将各种js/Vue文件打包成一个JS文件,打包过后就完全没有模块的概念了,然后我们在index.html 文件里面就引用这一个JS文件,就不会出错了。
webpack配置文件
Webpack默认的配置文件是项目根目录下的 webpack.config.js
。
var path = require('path'); // 这里是引用了Node的一个固定模块,因为我们需要使用path的resolve方法
module.exports = {
entry: './main.js', // 很好理解,打包的入口文件
output: {
path: path.resolve(__dirname, '../dist'), // resolve会将参数变成绝对路径返回,而__dirname是Node里面的一个参数,表示当前工程项目的绝对路径,打包文件放在dist文件夹里
filename: 'bundle.js'
},
mode: 'none' // mode是Webpack的打包模式,默认是'production',表示给生产环境打包的
};
module.exports是CommonJS模块导出语法,导出的是一个对象,该对象的属性就是Webpack打包要使用的参数。
Loader
在webpack里面,loader是很重要的,因为webpack只能打包JS和JSON文件
,而css文件就需要 css-loader和style-loader来帮助打包css文件,还有一些图片加载就需要 url-loader 等。
css-loader是解析CSS文件。它的作用也仅仅是解析CSS文件,它会把CSS文件解析后,以字符串的形式打包到JS文件中
,不过,此时的CSS样式并不会生效,因为我们需要把CSS插入到html里才会生效。
style-loader可以把JS里的样式代码插入到html文件里
。它的原理很简单,就是通过JS动态生成style标签插入到html文件的head标签里。
利用npm下载style-loader 和 css-loader,然后在配置项module里进行配置:
const path = require('path');
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}]
},
mode: 'none'
};
这个配置项名为何叫module?
Module是模块的意思,因此用这个名字可以表示这个配置项是用来解析与处理模块的
Module配置项里最重要的一个配置子项就是rules了,它定义了loader的处理法则
。rules是一个数组,里面放置着一个个JS对象,而在对象里面比较重要的便是test和use。
test表示正则表达式,用来匹配要处理的模块
use则是要使用的loader
entry
从当前根目录下的main.js开始打包,打包得到bundle.js。entry表示的就是资源入口文件,我们可以看到它是一个相对路径
。
context
上面的配置实际上省略了context的配置,Webpack官方称之为基础目录( base directory):
module.exports = {
context: path.resolve(_dirname,'./src'),
entry: './main.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js'
}
}
context在Webpack中表示资源入口entry是从哪个目录为起点的
。一般我们不会去设置context,在我们没有设置context的时候,它是当前工程的根目录。
context是一个绝对路径,是基础目录的意思;entry是一个相对路径,它与context拼接起来,就是Webpack打包的入口文件了。
entry 入口表达形式
1、第一种表达就是很简单的字符串,表示入口的js文件
2、第二种表达是数组,数组里面有多个字符串,注意,只有最后一个字符串是入口js,前面的都是想要引入到入口文件的
举个🌰:
entry: ['src/class', 'src/student', './main.js'],
上面的引入等价于:
main.js文件
import class from 'src/class';
import student from 'src/student';
entry: './main.js',
3、第三种表达是对象的形式
module.exports = {
entry: {
app: './src/main.js' // 主入口文件
},
output: {
path: path.resolve(__dirname, ''),
filename: '[name].js'
},
mode: 'none'
}
对象的表达就很好理解了,当我们进行懒加载希望一个大的JS文件打包成很多个不同的文件时,就利用这种方法。
output
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js',
publicPath:
}
下面来了解一下webpack的output的各项属性:
filename:打包后的JS文件名称,也可以是相对路径形式,最终打包的文件地址是 path + filename
这里要说明一下上面曾经用到过的 [name]
[name] 表示的是chunk的名称,简单来讲,一个chunk就是一个打包入口文件,当然,一个异步模块也是一个chunk。 具体之后再讲。
path:资源打包后输出的位置,绝对路径,webpack4默认为dist目录。
注意:path是打包文件生成的只是磁盘地址。
publicPath
这个属性要比上面两个属性难理解,所以需要好好的解释一下:
publicPath: 资源访问路径
举个🌰:
当我们打包好工程项目Vue后,我们就一般把打包好的文件夹放到服务器的tomcat上,然后通过浏览器来访问它,这里的publicPath就是我们如何读取磁盘的资源,和path不同,path是生成时的磁盘路径。
output.publicPath的表示形式有两大类:相对路径与绝对路径:
1、以 "./“或”…/"等开头,表示要访问的资源以当前页面url作为基础路径
假设我们要访问的url是:https://www.marksystem.com/class/
publicPath: "" // 访问地址 https://www.marksystem.com/class/bundle.js
publicPath: "../dist/" https://www.marksystem.com/dist/bundle.js
publicPath: "./dist/" https://www.marksystem.com/class/dist/bundle.js
2、以"/"开头,表示要访问的资源以当前页面的服务器地址作为基础路径
publicPath: "/" https://www.marksystem.com/bundle.js。
publicPath: "/dist/" https://www.marksystem.com/dist/bundle.js。
chunkFileName
chunkFilename也是用来表示打包后生成的文件名,但是注意,这里不包括入口文件,简单来讲就是异步加载后的一个个打包文件。
plugin
plugin也是为了扩展webpack的功能,从打包优化和压缩,到重新定义环境变量,功能强大到可以用来处理各种各样的任务。所以可以认为plugin是帮助进行优化的。
plugin项是一个数组,数组里面便是一个个plugin插件:
plugins: [
new webpack.HotModuleReplacementPlugin(), // 只是举个例子 这时webpack社区提供的
new CleanWebpackPlugin() // 这是plugin提供的
]
CleanWebpackPlugin
介绍一下这个插件,我们每次build生成的时候,都会在本地磁盘里面生成一个文件,这个插件就是帮助我们每次生成会把旧的先删除,然后再生成新的,减少对磁盘空间的占用。
npm install clean-webpack-plugin@3.0.0
然后就是真正的使用,但是记住,使用之前要先引用的:
var path = require('path');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
},
plugins:[
new CleanWebpackPlugin()
],
mode: 'none'
};
CopyWebpackPlugin
这个插件使用来复制文件的。在我们使用Webpack的时候,有一些本地资源,例如图片和音视频,在打包过程中没有任何模块使用到它们,但我们却想要把它们放在打包后的资源输出目录,copy-webpack-plugin这个插件就可以帮助我们完成这个事情。
举个简单的🌰: static目录下的静态资源需要copy-webpack-plugin
和上面的步骤一样,首先npm下载,然后require引入,之后放进plugins数组里面,但是不同于上面的无参数插件,这个插件是有参数需要配置的,让我们来看看:
参数是一个数组,数组里面是一个个对象,所谓对象,就是需要一个个处理的静态资源
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'), // 静态资源绝对路径
to: path.resolve(__dirname, '../dist/static') // 打包进入静态文件夹
}
]),
plugin 专门进行优化和性能提升。
举个🌰:
CommonChunkPlugin 主要用于提取第三方库和公共模块,避免首屏加载的bundle文件,或者按需加载的bundle文件体积过大,导致加载时间过长
针对html文件打包和拷贝的插件:html-webpack-plugin
开发环境配置
我们平时写完代码,希望能够在浏览器上测试查看一下,但是如果每次都是真实环境的打包,太浪费时间,而且需要手动刷新页面,因此webpack提供了一个开发环境测试,每次我们写完代码,可以自动更新浏览器页面内容。
当我们创建Vue项目的时候,Vue2.0包含了对于webpack的封装,你会在build文件夹里面看到 webpack.base.conf.js webpack.dev.conf.js webpack.pron.conf.js
这三个文件,其中webpack.base.conf.js 是无论开发还是生产环境都需要的,然后通过两个不同的文件封装两个环境需要的配置。
下面我们就创建一个Vue2.0项目,然后里面就有了一些webpack的配置了:
那么问题就是,我们是怎么运行webpack.dev.conf.js 文件的呢,这里我们聊一下平时的习惯,我们创建一个Vue项目后,首次肯定想运行一下看一下,然后我们会执行:
npm run dev
注意,我们运行了dev指令,那么这个指令究竟是什么呢,让我们打开package.json文件,看一下:
原来我们是简化了webpack.dev.conf.js运行指令,简化成dev了。
下面我们就来了解一下webpack.dev.conf.js文件吧。
文件监听模式watch
我们开始说过,我们希望修改代码后自动更新,那么就需要一个监听来监听我们的修改,从而实现更新,这就是webpack的文件更新监听watch。
启动watch就是依靠 webpack -watch指令启动,当然,这样子不太好用,后面发展直接使用了另外一种方法。
webpack-dev-server
webpack-dev-server是webpack提供的一种工具,平时叫做DevServer,安装并使用它后会在本地开启一个web服务器,可以用来处理网络请求。
npm install webpack-dev-server
在启动webpack-dev-server时,它会自动帮我们启动webpack并读取本地的webpack配置文件,同时它会启用webpack的文件监听模式。
source map
当我们利用webpack打包文件后在浏览器中打开,就会显示我们调试好的项目,但是打开源码,发现出现的是打包好后没有可观性的压缩代码,这样子也不利于开发修改bug,因此我们需要一个工具来帮助我们展示最开始的代码,这就是source map
。
要开启source map功能很简单,只需要在Webpack的配置文件里加一行配置就可以了:
devtool: 'source-map'
在生产环境,我们通常是不需要source map的,因为有泄露原始代码的风险
。
生产环境
生产环境与开发环境有很多的配置是相似的,但是最最不同的便是它们的开发环境,因此这里主要讲解一下开发环境的问题。
环境变量
在我们使用Webpack的过程中,会遇到两种环境变量。
Node.js环境里的环境变量
Webpack打包模块里的环境变量
Nodejs环境变量
Node.js环境里的环境变量,指的是用Node.js执行JavaScript代码时可以取到的环境变量,它都存放在process.env模块
。
webpack打包的环境变量
webpack打包的环境变量决定了代码运行在开发环境还是生产环境,通过DefinePlugin插件来设置打包模块里的环境变量
。
也就是在plugins数组里面放入DefinePlugin插件,在插件里面放入环境变量参数。
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env') // 开发环境 'env' 生产环境
})
]