webpack可以项目管理,项目打包,模块管理(依赖管理),加载器(js,css,html,png,jpg,woff,vue等),转换器(loader)。是基于node.js开发出来的一个前端工具
1.运行 npm install webpack -g 全局安装webpack,这样就能在全局使用webpack命令
2.在项目跟目录中运行npm i webpack安装到项目依赖中
webpack-study
文件夹index.html
,也可创建js,css,image文件夹,来分别存放想要的文件jQuery
前,先初始化项目npm init -y //直接创建,不会出现选项
npm i jquery -S //安装jQuery类库
import $ from 'jquery' //该导入方法为ES module
//webpack模块化开发支持多种模块化
//包括
//AMD:require.js
//CMD:sea.js
//common.js:node.js
//es6:ES module
7.直接在文件中使用main.js
文件会报错,因为浏览器不认识import
这种高级JS语法,需要使用webpack进行处理,webpack默认会把这种高级的语法转化为低级的浏览器能够识别的语法;
8.webpack 入口软件路径 出口文件路径
对index.js进行处理
webpack ./src/main.js ./dist/bundle.js
9.webpack4允许我们指定编译使用开发模式还是生产模式,这由mode
进行控制,value为枚举值:development/production
,分别对应开发模式和生产模式(这个配置可以作为命令行的配置参数也可以作为配置文件中的一个配置项,默认值为production
,即生产模式)
1 | webpack ./src/main.js ./dist/bundle.js --mode development
webpack.config.js
文件webpack.config.js
中配置这两个路径://导入处理路径的模块,该模块node.js中自带
const path = require('path');
//导出一个配置对象,将来webpack在启动的时候
//会默认来查找webpack.config.js,读取这个
//文件中导出的配置对象,来进行打包处理
//使用了common.js模块化导出
module.export = {
//配置打包模式为开发模式
mode: 'development',
//配置入口文件,最好是创建一个对象,这样可以设置导出文件名,
//并且webpack会把对象里面的文件分别打包成一个js文件
//如果是数组,webpack会把数组中的所有文件打包成一个js文件
entry:{
main:path.resolve(__dirname, 'src/main.js')//表示在根目录下的文件
},
output:{
path:path.resolve(__dirname, 'dist'), //配置输出文件路径
filename:'[name][hash].js' //[name]表示用原有的chunk名称,
//[hash]利用md5命名,目的用于浏览器的缓存机制
}
}
当我们在控制台中直接输入webpack命令执行的时候,webpack做了以下几步
1.webpack发现没有通过命令行的形式给出指定入口和出口文件
2.webpack就会去项目的根目录中直接查找一个名为webpack.config.js
的配置文件
3.当查找到配置文件后,webpack会去解析执行这个配置文件,当解析执行完配置文件后,就得到了配置文件导出的配置对象
4.当webpack得到配置对象后,就拿到了配置对象中指定的入口和出口文件,然后进行打包构建
webpack-dev-server
来实现自动带包编译功能,当修改完代码后,会自动进行打包编译npm install webpack-dev-server -D
安装到开发依赖中webpack-dev-server
会报错,由于我们项目是在本地安装的,所以无法把它当做我们的脚本命令在命令行终端中直接运行(只有那些安装到全局-g
的工具,才能在终端运行)npm install webpack -D
webpack-dev-server
还会报错,那么此时需要借助package.json
文件中的指令,来运行webpack-dev-server
命令,在scripts
节点下新增"dev": "webpack-dev-server"
指令,然后直接运行这个指令npm run dev
发现实时打包webpack-dev-server
帮我们打包生成的出口文件,并没有存放到实际的物理磁盘上,而是直接托管到了电脑的内存中,所以我们在项目根目录中根本找不到这个打包好的出口文件webpack-dev-server
把打包好的文件以一种虚拟的形式托管到了咱们项目中的根目录中,虽然我们看不见它,但是我们可以认为在dist文件夹中package.json
中scripts
中的配置"dev": "webpack-dev-server --open"
12.修改了package.json
文件,所以要重启服务器,npm run dev
13.修改端口
"dev": "webpack-dev-server --open --port 3000"
14.启动服务器后打开的http://localhost:3000/
网站,发现会出现一个文件夹面板,需要点击到src目录下,才能打开index.html首页,所以,为了打开网站后直接打开index首页,可以配置为
"dev": "webpack-dev-server --open --port 3000 --contentBase src"
15.每次修改了文件后,在浏览器中还要刷新才能实时的把修改的内容添加到浏览器中,所以可以配置热更新来进行无刷新加载页面,热更新,不会重新生成新的出口文件,会把修改的内容以补丁的形式添加到出口文件中
"dev": "webpack-dev-server --open --port 3000 --contentBase src --hot"
devServer:{
open:true, //自动打开浏览器
port:3000, //设置启动时候运行的端口
contentBase:"src", //指定托管的根目录
hot:true, //启动热更新
}
如果页面没有加载并报错
1.在头部引入webpack
模块
const webpack = require("webpack")
2.在plugins节点下新增
plugins:[
new webpack.HotModuleReplacementPlugin()
]
每次打包生成的HTML文件都要手动引用js文件,如何解决呢
1.安装
npm i html-webpack-plugin -D
2.配置webpack.config.js
const htmlWebpackPlugin = require("html-webpack-plugin")
3.在plugins中设置
plugins:[
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
template:'./src/index.html',//以当前目录下的index.html文件为模板生成dist/index.html文件
filename:'index.html',//输出的文件名
})
]
最后会发现打包好的index.html中多生成了一个
<srcipt type='text/javascripte' src='./bundle.js'></script>
直接插入页面自动追加
使用创建clean-webpack-plugin
,删除指定文件,更多配置,因为打包后会在dist中一直生成出口文件,出现重复文件,所以在重新打包时,删除上次打包的文件
1.安装
npm i clean-webpack-plugin -D
2.配置webpack.config.js
const cleanWebpackPlugin = require("clean-webpack-plugin")
3.在plugins中设置
plugins:[
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
template:'./src/index.html',//以当前目录下的index.html文件为模板生成dist/index.html文件
filename:'index.html',//输出的文件名
}),
new cleanWebpackPlugin(['dist']),//错误配置,传入数组,指定要删除的目录
new cleanWebpackPlugin(), //正确配置
]
4.执行npm run dev
可以看出dist目录被删除,又生成一个新的dist目录,之前的js文件被删除
webpack
默认只能打包处理js类型的文件,无法处理其他非js的文件loader
加载器loader
是什么呢?它就是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,单纯的文件转换过程。也能够对文件进行一些处理,诸如编译、压缩、等,最终一起打包到指定的文件中注意
处理一个文件可以使用多个loader
,loader
的执行顺序和配置中的顺序是相反的,即最后一个loader
最先执行,第一个loader
最后执行
第一个执行的loader
接收源文件内容作为参数,其他loader
接收前一个执行的loader
的返回值作为参数,最后执行的loader
会返回此模块的JavaScript源码
4.想要打包处理css文件,想要安装
npm i style-loadr css-loader -D
5.打开webpack.config.js
这个配置文件,在里面新增一个配置节点,叫做module
,它是一个对象,在这个对象上,有一个rules
属性,该属性为数组,这个数组中存放了所有第三方文件的匹配和处理规则
module:{
rules:[{
text:/\.css$/,
use:[{
loader:style-loader
},
{
loader:css-loader
}
]
}]
}
6.webpack 处理第三方文件类型的过程
1.发现这个要处理的文件不是js文件,然后就去配置文件中,查找有没有对应的第三方loader规则
2.如果能找到对应的规则,就会调用对应的loader处理这种文件类型
3.在调用的时候,是从后往前调用
4.当最后一个loader调用完毕,会把处理的结果交给webpack打包合并,输出到打包文件中
npm install extract-text-webpack-plugin -D
2.webpack.config.js配置
const ExtractPlugin = require('extract-text-webpack-plugin')
3.正式环境中去掉style-loader
,因为style-loader
是将css-loader
处理后的内容外面包了一层js代码,这个js代码就是把css写进html里,写成style标签。正式环境需要拆分出单独的css文件,所以不需要style-loader
module:{
rules:[{
text:/\.css$/,
use:ExtractPlugin.extract[{
fallback:'style-loader',
use:[{
loader:css-loader
}]
},
]
}]
}
4.添加一个插件
plugin:{
new ExtractPlugin('style.[constentHash:8].css'),//打包后的文件名
}
webpack
中,默认只能处理一部分es6
新语法,一些高级的es6
语法或者es7
语法webpack处理不了,这时候,就需要借助第三方loader
,来帮助webpack
处理这些高级的语法,当第三方loader
把高级语法转为低级语法之后,会把结果交给webpack
打包到bundle.jsnpm install babel-core babel-loader babel-plugin-transform-runtime --save-dev
3.安装babel转化的语法
npm install babel-preset-env babel-preset-stage-0 --save-dev
4.打开webpack的配置文件,在module节点下的rules数组中,添加一个新的匹配规则
{
test:/\.js$/,
use:'babel-loader',
exclude:/node_modules/
}
5.注意在配置babel
的loader
规则的时候,必须把node_modules
目录通过exclude
选项排除掉,原因如下
如果不排除
node_modules
,则babel
会把node_modules
中所有的第三方js文件,都打包编译,这样会非常消耗cpu,同时。打包速度非常慢
哪怕最终,babel把所有的node_modules中的js转换完毕了,但是项目也无法正常运行
6.在项目根目录中,新建一个 .babelrc
的 babel
的配置文件,这个配置文件,属于json格式语法规范,不能写注释,字符串必须用双引号
{
"presets":["env","stage-0"],
"plugins":["transform-runtime"]
}
.vue
文件,需要安装相关的loadernpm install vue-loader vue-template-compiler -D
2.在配置文件中,新增loader配置项
{
test:/\/vue$/,
use:{
loader:'vue-loader'
}
}
3.在webpack中,如果想要通过 Vue
把一个组件放到页面中去,以实例中的 render
函数可以实现
4.如果报错,说明在 webpack.config.js
文件中没有配置好
const vueLoaderPlugin = require('vue-loader/lib/plugin')
plugin:{
new vueLoaderPlugin()
}
概念问题一:什么是webpack和grunt和gulp有什么不同?
答案:webpack是一个模块打包器,他可以递归的打包项目中的所有模块,最终生成几个打包后的的文件,他和其他的工具最大的不同在于他支持code-splitting(代码分割)、模块化(AMD、ESM、Common.js)、全局分析
概念问题二:什么是bundle,什么是chunk,什么是module?
答案:bundle是由webpack打包出来的文件,chunk是指webpack在进行模块的依赖分析的时候,代码分割出来的代码块,module是开发中的单个模块
概念问题三:什么是loader?什么是plugin?
答案:loader是用来告诉webpack如何转化处理某一类型的文件,并且引入到打包出的文件中
plugin是用来自定义webpack打包过程的方式,一个插件是含有apply方法的对象,通过这个方法可以参与到整个webpack打包的各个流程(生命周期)
概念问题四:如何可以自动生成webpack配置?
答案:webpack-cli / vue-cli /etc 各种脚手架工具
开发问题五一:webpack-dev-server和http服务器如nginx有什么区别?
答案:webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,他比传统的http服务对开发更加简单高效
开发问题二:什么是模块热更新?
答案:模块热更新是webpack的一个功能,他可以使得代码修改过后不用刷新浏览器就可以更新,是高级版的自动刷新浏览器
优化问题一:什么是长缓存?在webpack中如何做到长缓存优化
答案:浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或是更新,都需要浏览器去下载新的代码,最方便和简单的更新方式ius引入新的文件名称。在webpack中可以在output给输出的文件指定chunkhash,并且分离经常更新的代码和框架代码。通过NamedModulePlugin或是HasnedModuleIdsPlugin使再次打包文件名不变
优化问题二:什么是Tree-shaking?CSS可以Tree-shaking吗
答案:Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码。在webpack中Tree-shaking是通过uglifyJsPlugin来Tree-shaking JS。CSS需要使用purify-CSS