1.了解Webpack
- 什么是webpack
- webpack是一个模块打包器(bundler)
- 在webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理
- 它会根据模块的依赖关系进行静态分析,生成对应的静态资源
- 四个核心概念
- Entry:入口起点(entry point)指示webpack应该使用哪个模块,来作为构建其内部依赖图的开始
- Output:告诉webpack在哪里输出它所创建的bundles,以及如何命名这些文件,默认值为 ./dist
- Loader:loader可以让webpack能够去处理那些非JavaScript文件(webpack自身只能解析:JavaScript、json)
- plugins:插件可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等
- 理解Loader
- webpack本身只能加载js/json模块,如果要加载其他类型的文件(模块),就需要使用对应的loader进行转换/加载
- 它本身是一个函数,接受源文件作为参数,返回转换的结果
- loader一般以xxx-loader的方式命名,xxx代表了这个loader要做的转换功能,比如json-loader
- 理解插件plugin
- 插件可以完成一些loader不能完成的功能
- 插件的使用一般是在webpack的配置信息plugins选项中指定
- CleanWebpackPlugin:自动清除指定文件夹资源
- HtmlWebpackPlugin:自动生成HTML文件
- UglifyJSPlugin:压缩js文件
- 配置文件(默认)
-
webpack.config.js:是一个node模块,返回一个json格式的配置信息对象
-
2.学习文档
- webpack官网:http://webpack.github.io/
- webpack3文档(英文):https://webpack.js.org/
- webpack3文档(中文):https://doc.webpack-china.org/
3.webpack的基本使用
1.生成package.json文件
2.安装webpack(都要安装):
- npm install webpack@3 -g //全局安装
- npm install webpack@3 --save-dev //局部安装
3.小试牛刀处理一个js
执行命令:webpack src/js/index.js build/index.js
观察发现webpack会把es6语法,直接编译为浏览器识别的模块化语法,不过类似于箭头函数等依然存在
4.使用webpack配置文件
webpack的核心文件:执行webpack命令时,会在当前目录查找webpack.config.js文件读取配置
1.通过commonjs暴露出去一个对象
2.四个关键的概念:
entry:入口文件,将所有打包资源全部引入
output:输出,将资源输出到指定目录下
loader:处理webpack不能够解析的模块
plugins:执行loader做不了的任务
3.如何找到自己想要的loader?
优先去官网找自己想要的loader,没有再去npm官网上找
4.在终端输入:webpack ./src/js/app.js ./build/js/build.js
问题:这种方式只能够编译打包js、json文件,其他文件处理不了
5.webpack --display-modules可以查看隐藏的任务
const path = require('path') //path内置的模块,用来设置路径
module.exports = {
//入口(从哪里进入开始解析)
entry:'./src/js/index.js',
//出口(最终加工完的代码输出到哪里)
output: {// 输出配置
path: path.resolve(__dirname, 'build'),//输出文件路径配置
filename: 'index.js',//输出文件名
}
}
5.在package.json中配置npm命令
"scripts":{
"build":"webpack"
}
//打包应用运行:npm run build
6.使用loader解析less文件(使用less-loader)
1.安装:npm install less-loader less --save-D
2.安装:npm install css-loader style-loader --save-D
3.向rules中写入配置:
{
test: /\.less$/,
use: [
{
loader: "style-loader" //创建一个style标签,将js中的css放入其中
},
{
loader: "css-loader" //将css以commonJs语法打包到js中
},
{
loader: "less-loader" //将less转换成css
}
]
}
4.在入口js中引入less文件:import '../less/demo.less'
7.file-loader处理图片资源
1.安装:npm install --save-dev file-loader
2.新增loader:
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader', //如果不做图片转base64,可以用file-loader
options: {
outputPath: 'img', //图片最终输出的位置
publicPath: '../build/img', //css资源图片路径
name: '[hash:5].[ext]' //修改图片名称
}
}
]
}
8.url-loader处理图片资源&base64
1.安装:npm install url-loader --save-D
2.修改loader为:
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader', // 如果不做图片转base64,可以用file-loader
options: {
limit: 8192,
outputPath: 'img', // 图片最终输出的位置
publicPath: '../build/img', // css资源图片路径
name: '[hash:5].[ext]' // 修改图片名称
}
}
]
}
3.备注:一定要注意路径的问题
9.使用插件提取css,合并为单独的文件
1.安装ExtractTextWebpackPlugin插件:npm install extract-text-webpack-plugin --save-D
2.引入插件:const ExtractTextPlugin = require("extract-text-webpack-plugin")
3.新增plugins插件配置项,并实例化ExtractTextPlugin插件:
plugins: [
//提取css为单独文件
new ExtractTextPlugin("./css/index.css")
]
4.修改原less-loader的配置如下:
{
test: /\.less$/, //匹配文件的规则,说明该loader对哪个文件生效
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "less-loader"]
})
}
5.备注:因为css提取成单独文件,不再包含在js中了,所以要修改url-loader配置publicPath为: '../img'
10.js语法检查
1.安装jshint-loader:npm i jshint-loader --save -D
2.新增loader:
{
test: /\.js$/, //涵盖.js文件
enforce: "pre", //预先加载jshint-loader
exclude: /node_modules/, //排除掉 node_modules 文件夹下的所有文件
use: [
{
loader: "jshint-loader",
options: {
//jshint的错误信息默认情况下会显示为warning(警告)类信息
//将emitErrors参数设置为true可使错误显示为error(错误)类信息
emitErrors: false,
//jshint默认情况下不会打断webpack编译
//如果你想在jshint出现错误时,立刻停止编译
//请设置 failOnHint 参数为true
failOnHint: false
}
}
]
}
3.备注:有一个小坑,就是仅仅安装jshint-loader还不够,
还要安装js-hint,命令:npm i jshint --save -D
11.es6转es5
1.安装babel-loader,命令:npm install babel-loader babel-core babel-preset-es2015 --save -D
2.配置新的loader
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
persets: ['es2015']
}
}
}
3.坑!提示找不到"@babel/core",根据提示执行:npm i babel-loader@7 --save -D
12.html文件的处理和清除文件夹
1.对于html的操作,虽然有了html-loader这个loader,不过功能有限我们的需求是:
想让webpack自动的帮我们创建一个html,然后把我们想要引入的东西引入进来,所以要借助插件。
2.使用插件HtmlWebpackPlugin,安装:npm install --save-dev html-webpack-plugin
3.引入插件:const HtmlWebpackPlugin = require('html-webpack-plugin')
4.新增一个插件配置项:
new HtmlWebpackPlugin({
title: 'webpack',
filename:'index.html',
template:'./src/index.html'
})
备注:要在html模板中写入<%= htmlWebpackPlugin.options.title %> ,title配置才生效
5.删除掉模板html中的所有引入
6.为了清空工作目录,安装插件:clean-webpack-plugin,命令:npm i clean-webpack-plugin -D
7.引入插件:const {CleanWebpackPlugin} = require('clean-webpack-plugin')
8.实例一个插件:
new CleanWebpackPlugin('./build')
备注:最新版的CleanWebpackPlugin不传任何参数
13.提取build环境配置文件
1.新建文件目录:config
2.移动webpack.config.js文件到config中,改名为:webpack.build.js
3.通过执行:webpack --display-modules --config ./config/webpack.build.js 指定配置文件运行
4.完善一下:在package.json中定义命令:
"build": "webpack --display-modules --config ./config/webpack.build.js"
5.以后可以通过:npm run build代替完整命令
6.【问题】:发现build文件夹出现在了config中,解决办法如下:
修改出口output中的path为:resolve(__dirname, '../build')
7.【问题】:上一步的清空位置发生了改变,解决办法如下:
修改CleanWebpackPlugin插件的配置如下:
new CleanWebpackPlugin('./build', {
root:resolve(__dirname,'../')
})
备注:如果使用的clean-webpack-plugin插件是2.0以上的,则不会出现问题7
14.提取dev环境配置文件(dev环境搭建)
1.复制一份webpack.build.js,改名为:webpack.dev.js
2.安装dev-server:npm i webpack-dev-server@2 -D(下载第2个版本,3版本有兼容性问题)
3.修改package.json的配置:"dev": "webpack-dev-server --config ./config/webpack.dev.js"
4.在webpack.dev.js中配置dev服务器编:
//配置开发服务器
devServer: {
hot: true,//热模替换
open: true,//自动打开浏览器
port: 3001,
compress: true//启用gzip压缩
}
备注:官网-->配置-->开发中server(devserver)可见详细配置
5.启用HMR(热模替换)
引入webpack:const webpack = require("webpack")
追加一个插件:new webpack.HotModuleReplacementPlugin()
6.存在的问题:改了css、html还得手动刷新才可以,解决如下:
7.【解决css无法模块热更新的问题】因为css用的是插件,不是loader,所以不行,解决办法:重新使用loader的方式
8.【解决html无法自动刷新的问题】因为html也是插件,办法:html依然用插件,追加使用loader,安装:npm i html-loader -D
新增html-loader配置项如下
{
test: /\.(html)$/,
use: {
loader: 'html-loader'
}
}
同时entry重写为:['./src/js/index.js','./src/index.html']
备注:需要注意的是:dev方式的运行是加载在内存中的,没有任何输出
15.提取公共代码实现复用
1.参考webpack.build.js,新增:webpack.common.js
2.webpack.common.js中删除所有css的loader,删除CleanWebpackPlugin,删除ExtractTextPlugin插件,删除最上方二者的引用
3.在webpack.build.js上方引入:const common = require('./webpack.common')
4.安装合并库:npm i webpack-merge -D,引入merge库:const merge = require('webpack-merge')
5.module.exports = merge(common,{当前文件所有配置})
6.剔除webpack.build.js中:入口,出口,图片处理,js语法检查,es6转换,HtmoWebpackPlugin
7.剔除webpack.dev.js中:出口,图片处理,js语法检查,es6转换,插件只保留:HotModuleReplacementPlugin
16.prod环境配置
复制webpack.build.js。改名:webpack.prod.js
package.json中追加:"prod": "webpack --display-modules --config ./config/webpack.prop.js"
pro模式输出的文件在dist文件夹中,修改出口配置:path:resolve(__dirname, '../dist'),filename: './js/[name].[hash:10].js'
修改css插件配置:new ExtractTextPlugin("./css/[name].[hash:10].css")
【压缩js】
使用插件(用于压缩js文件):UglifyjsWebpackPlugin
引入webpack:const webpack = require('webpack')
插件中新增配置:new webpack.optimize.UglifyJsPlugin({sourceMap:true})
追加一个配置(与插件同级):devtool:'source-map'
【css扩展前缀】
使用loader:postcss-loader,执行安装:npm i -D postcss-loader
在css的loader配置中加入postcss-loader:use: ["css-loader","postcss-loader","less-loader"]
在根目录新建postcss.config.js文件,配置如下内容:
module.exports = {
"plugins": {
"autoprefixer": {
"browsers": [
"ie >= 8",
"ff >= 30",
"chrome >= 34",
"safari >= 7",
"opera >= 23"
]
}
}
}
安装所需的autoprefixer,命令:npm i autoprefixer -D
【压缩css】
使用less-plugin-clean-css插件,命令:npm i less-plugin-clean-css -D
引入插件:const CleanCSSPlugin = require("less-plugin-clean-css")
替换use中的less-loader为对象,如下:
loader: "less-loader",options: {
plugins: [
new CleanCSSPlugin({ advanced: true })
]
}
【压缩html】
将webpack.common.js中的HtmlWebpackPlugin插件复制过来
追加一个配置项:minify:{ removeComments:true, collapseWhitespace:true }
webpack面试题
1.webpack的核心概念
Entry:入口,webpack进行打包的起始点(文件)
Output:出口,webpack编译打包生成的bundle(打包文件)
Loader:模块加载(转换)器,将非js、非json模块包装成webpack能理解的js模块
Plugin:插件,在webpack构建流程中的特定时机插入具有特定功能的代码
Module:模块,在webpack眼中一起皆模块,默认只识别js文件,如果是其他类型文件利用对应的loader转换为js模块
2.webpack配置文件的整体结构
module.exports = {
entry: '', //入口
output: {}, //输出
module: {rules: []}, //配置loader
plugins: [] //配置plugin
}
3.webpack模块化打包的基本流程
1.连接:webpack从入口js开始,递归查找出所有相关联的模块,并【连接】起来形成一个图(网)的结构
2.编译:将js模块中的模块化语法【编译】为浏览器可以直接运行的模块语法(当然其他类型资源也会处理)
3.合并:将图中所有编译过的模块【合并】成一个或少量的几个bundle文件,浏览器真正运行是打包生成的bundle文件
4.比较loader与plugin
1.loader:用于加载特定类型的资源文件,webpack本身只能打包js。
2.plugin:用来扩展webpack其他方面的功能,一般loader处理不了的资源,完成不了的操作交给插件处理。
5.区别live-reload(自动刷新)与hot-realod/HMR(热模替换)
相同点:
代码修改后都会自动重新编译打包
不同点:
live-reload:刷新整体页面,从而查看到最新代码的效果,页面状态全部都是新的。
Hot-reload:没有刷新整个页面,只是加载了修改模块的打包文件并运行,从而更新页面的局部界面,整个界面的其他部分的状态还在
6.webpack常用loader与plugin汇总
loader:
1.【less-loader】:用于将less文件翻译成为css
2.【css-loader】:用于将css以commonjs语法打包到js中
3.【style-loader】:用于动态创建一个style标签,将css引入页面
备注:上述三个loader一般配合使用,最终实现:翻译less为css,以style标签形式将样式引入页面
4.【file-loader】:提取源代码图片资源,到指定位置,可修改文件名等操作
5.【url-loader】:与file-loader功能几乎一致,优势是可以对图片进行动态转换base64编码(控制limit属性值可以控制阈值)
备注:上述两个loader中url-loader应用比file-loader广泛
6.【jshint-loader】:对项目中的js语法进行检查,可选的配置项有:
emitErrors: true/false
-- emitErrors为true,检查出的错误显示为error(错误)类信息
-- emitErrors为false,检查出的错误显示为warning(错误)类信息
failOnHint: true/false
-- failOnHint为true,当jshint检查出错误时,直接打断当前的代码的编译
-- failOnHint为false,当jshit检查出错误时,会继续编译
esversion:6
-- 告诉jshint,不再提示新语法兼容性问题(有专门的loader解决新语法问题)
-- 自定义一个报告错误的函数,输出想要的内容
reporter: function(errors) {}
-- 自定义一个报告错误的函数,输出想要的内容
7.【babel-loader】:将es6语法转换为es5语法
备注:该loader的使用要借助:babel-loader babel-core babel-preset-es2015
8.【postcss-loader】:用于扩展css前缀
备注:
(1).该loader需要一个postcss.config.js配置文件
(2).该loader要配合autoprefixer库使用
(3).该loader使用的时机为:["css-loader","postcss-loader","less-loader"]
pulgin:
1.【extract-text-webpack-plugin】:用于提取项目中的css,最终合并为一个单独的文件。
备注:上述插件需要配合:css-loader、less-loader两个loader使用,css-loader、less-loader处理之后,交给extract-text-webpack-plugin处理
2.【html-webpack-plugin】:自动创建html文件,且自动引入外部资源。配置项如下:
title:"webpack",
filename:"index.html",
template:"./src/index.html"
//用于压缩html
minify:{
removeComments: true, //移除注释
collapseWhitespace: true //移除换行
}
3.【clean-webpack-plugin】:清空webpack的输出目录,防止其他文件“乱入”
4.【HotModuleReplacementPlugin】:热模替换(HMR)插件
备注:1.该模块必须配合webpack-dev-server模块使用,且webpack-dev-server中必须启用HMR
2.想要让指定文件支持HMR,必须要:
(1).无论是否有插件操作过该类型的资源,最终必须交给loader处理
(2).必须在入口文件中声明使用。
5.【UglifyJsPlugin】:压缩js的插件,且可以生成sourceMap映射文件,用于方便排查错误
6.【less-plugin-clean-css】:压缩css文件,在less-loader翻译less文件之后,该插件介入,开始压缩