一、webpack4初识
1.首先先了解几个规范
ES规范,导出:export default Header;
导入:import Header from ‘./header.js’;
CommonJS规范,导出:module.exports = Header;
导入:var header = require('./header.js');
其他规范CMD,AMD
2.给出一个小的项目
如果该项目不用webpack打包根本并不会正确运行,因为浏览器并不会识别导入导出的js语法,但是webpack可识别这些语法
首先 npm init 初识化项目,然后npm install webpack webpack-cli -D/--save-dev 进行安装webpack
将index.js文件打包,npx webpack index.js
这时候在导入生成的dist目录下的main.js即可正常运行项目
但是就会有人说了,那webpack不就是js的翻译器么,这样说其实是夸大了他的功能,因为他只能识别很少部分js
二、webpack的安装
1.全局安装:npm install webpack webpack-cli -g
缺点:一旦全局安装,如果一个项目webpack3,一个项目webpack4 有一个项目就跑不起来了
在项目中安装npm install webpack webpack-cli -D/--save-dev
2.小点补充:(1)npm info webpack 可以车看webpack中所有的版本
(2)npm install webpack@xxxxx webpack-cli -D版本号安装
(3)一般github的项目中都没有node_moudle文件,想让项目跑起来,在项目中执行命令 npm install 即可
三、简单利用webpack配置文件
配置文件webpack.config.js和package.js文件的配置和修改,以及目录结构的变化
修改了package.js中的scripts中的启动命令后就不用npx webpack 了用npm run boundle 即可
补充,上边的入口配置实际是简写,写全是main:xxx,然后模式默认为mode:production (js文件压缩形式) mode:development(js不压缩)
四、file-loader(可用于图片打包) url-loader
url-loader的使用和file-loader类似,特别之处在于:url-loader如果未超过限定的大小,回打包到js文件中,这样一个小的图片文件就不会在发送一次http请求了;如果超过了限定大小,会打包到image文件夹下,这样不会使js文件过大,不会导致页面出现一大段时间的空白。
webpack.config.js文件
module:{
rules:[{
test:/\.(png|jpg|gif)$/,
use:{
loader:'file-loader',
options:{
name:'[name]_[hash].[ext]',
outputPath:'images/'
}
}
}]
},
module:{
rules:[{
test:/\.(png|jpg|gif)$/,
use:{
loader:'url-loader',
options:{
name:'[name].[ext]',
outputPath:'images/',
limit:2048
}
}
}]
},
这里的2048是2kb
五、css-loader等等样式打包
1.先介绍简单的css打包
npm install style-loader css-loader -D
2.接下来介绍一下更高级一点的,比如sass、less等等
npm install sass-loader node-sass --save-dev
{
test:/\.scss$/,
use:['style-loader','css-loader','sass-loader']
}
3.对于一些css3新特性的使用(加前缀,-webkit- -moz-):
npm install -D postcss-loader
但还有引用第三方的插件
npm install autoprefixer -D
然后根据官方文档进行配置
//新建一个postcss.config.js配置文件,内容如下
module.exports = {
plugins: [
require('autoprefixer')
]
}
//webpack.config.js
{
test:/\.scss$/,
use:[ 'style-loader',
'css-loader',
'sass-loader',
'postcss-loader'
]
}
其实这些loader是有顺序的,从下向上,从右向左,先是执行postcss,然后找是否是sass,接着将scss转成css最后style挂在到页面上
4.若在sass文件中有引入了sass文件,如果像上边那样配置的话,引入的那个sass文件就不会被翻译过来了,因为不会走下边的sass-loader和postcss-loader这两个loader了,直接走css-loader,如果新配置了importLoader: 2 这个意思是,不管js引入的sass文件,还是sass文件中引入的sass文件都会从下往上走进行编译
5.只在一个作用域内使css生效,模块化css,配置:modules:true注意引入时要给css文件加一个名字,并且引入其中的类名时要用 名字.类名
5. 关于图标字体的使用
图标的引入时利用了iconfont阿里图标库,如果第一次接触的话可有百度一下
将下载下来的css文件引入自己需要的位置并注意除了base64以外都需要修改字体路径,在这里就相当于了svg、woff文件的引入,所以不用在import了,进行配置webpack.config.js
module:{
rules:[{
test:/\.(png|jpg|gif)$/,
use:{
loader:'url-loader'
}
}]
}
六、关于html-webpack-plugin、clean-webpack-plugin的使用
1.html-webpack-plugin 安装这个插件后将在打包目录里自动生成index.html并将想打包的js引入进js中
npm install --save-dev html-webpack-plugin
关于配置,最常用的参数是template,以一个html文件为模板来生成打包目录的html
var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
2.clean-webpack-plugin
npm install --save-dev clean-webpack-plugin
每次打包都清除之前的dist打包目录,就不用手动删除上一次遗留下来的东西了,同上边的配置和引入,注意自己调整一下参数即可,注意这个的引入有点特殊。要用const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’),要加一个大括号
综上,其实plugin就相当于vue中的生命周期钩子,在打包的不同节点自己自动执行。
七、关于source-map
他其实是一个映射关系,默认情况下他是devtool:‘none’是关闭的,即当我们的某些代码写错时,打包的git不会报错,但是控制台会报错,不配置的话他报错的位置是打包后文件的位置,根本找不到在原来的那个文件有代码错误,配置后便能很好的映射到原来的文件位置,查到后便可修改了。
module.exports = {
mode:'production',
devtool:'source-map'
}
还有inline-source-map等等等,自己下去了解一下
八、关于每次修改完页面,均不用再去打包一遍了(devServe)
现在来介绍三种方法:
第一种:但是要注意项目第一次打包的之后要用 npm run watch,每次修改完就不用打包了,直接刷新页面就行
//修改package.json中的配置项
"scripts": {
"bundle": "webpack",
"watch":"webpack --watch"
}
第二种:devServer,这种他会自动开启一个服务器,对比上一中的好处是都不用刷新了,实时更新修改
配置webpack.config.js devServer:{ contentBase :‘./dist’}
package.json "start":"webpack-dev-server"
九、HotMoudleReplacement热模块替换
用devServer打包时会发现没有dist目录了,这是因为他自动存入了内存,从而使打包速度更快,若想看到dist目录,就用
npx webpack
模块配置:
const webpack = require('webpack');
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
],
devServer:{
contentBase:'./dist',
open:true,
hot:true,
hotOnly:true//即使HMP不生效,浏览器也不会自动刷新
}
若css效果发生了改变,页面只会刷新使用的那部分css,不会刷新整个页面,注意这个插件是webpack自带的,所以不用安装,但是要require(‘webpack’),配置时用new webpack.HotMoudleReplacementPlugin()
上面只是介绍的css文件改变时,应该怎么办,但其实也可能一个index.js中引入过了js文件,其中一个引入的一个js文件发生变化时,如果还按照上面的方法配置将会导致文件改变页面也没有效果,所以这样做
//index.js中的内容
import counter from './counter.js';
import number from './number.js';
counter();
number();
//若在开发过程中number.js发生变化
if(module.hot){
module.hot.accept('./number', () => {
//保证将上一次产生的结果清除掉
document.body.removeChild(...);
number();
})
}
之所以css不用这样写,是因为css-loader已经帮忙实现了,就不用自己写了
十、babel ES6
将由于一些比较不够与时俱进的浏览器无法识别ES6语法,转换为ES5的语法,关于配置可参照babel的官方网站 Setup-webpack
首先进行安装
npm install --save-dev babel-loader @babel/core
npm install @babel/preset-env --save-dev
webpack.config.js配置
{
test: /\.js$/,
exclude: /node_modules/, //如果js文件时在node_modules文件中,就不试用babel-loader了第三方的模块没有必要转ES5
loader: "babel-loader" ,
options:{
"presets": ["@babel/preset-env"]
}
这样打包就可以了,ES6的语法变成了ES5的语法,但是光是这样子是不够的,例如promise这种在低版本的浏览器中还是不存在的,所以不仅要用@babel/preset-env做语法的转换,还要讲这些确实的东西补充进低版本浏览器中,使用@babel/polyfill,首先进行安装
npm install --save @babel/polyfill
但是问题又来了,打包后的文件特别大,是因为我们将除了promise和map的其他方法也打包进来了,但我们这个项目的业务代码只用到了promise和map所以我们只需这两个就行,就需要一个配置参数
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options:{
presets: [['@babel/preset-env',{
useBuildIns:'usage'
}]]
}
}
还有一个问题是,如果你开发类库组件库时,用这种方案是有问题的,因为babel-polyfill会让浙西方法全局注入,会污染全局环境,所以我们要换一种配置方式:注释掉import "@babel/polyfill"并安装:
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options:{
// presets: [['@babel/preset-env',{
// useBuildIns:'usage'
// }]]
"plugins": [["@babel/plugin-transform-runtime",{
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false
}]]
}
}
如果只是简单业务代码那么只需要presets和import "@babel/polyfill"即可,如果是库项目那就要写下边的一大堆plugins了,注意适应场景不同
我们发现babel的配置参数特别多特别长,所以我们可以吧他们放在一个文件中 .babelrc