Webpack
概念
webpack 把所有的东西全部看成模块:js、css、图片、字体库等静态资源。
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
webpack:打包、编译;面向对象
gulp:面向过程
模块开发化语法
- commonJS(AMD)语法:module.exports(exports) --require()
- es6语法:export(default)—import
//当前文件夹也必须加./
import stu from "./Modular-export.js"
console.log(stu);//{name: "lily", age: 18}
//模块化的特点
// 1.import 语句是编译时引入,异步引入;只允许使用在最顶层(最外层 语句嵌套的最顶层),不能实现按需引入
// function fun(isTrue) {
// if (isTrue) {
// import stu from "./Modular-export.js"
// console.log(stu);
// }
// }
// 2.数据量加载 模块化 节省内存
// 3.浏览器有缓存,运行速度更快
import { num, say } from "./Modular-export.js"
console.log(num);//100
say();//hello
//module.export --require()这种形式没有加入es6规则
//这两句需要在node.js里运行 浏览器不支持
//cmd窗口中 找到目录运行==> node js路径
let mydata=require("./Modular-export.js")
console.log(mydata);
//Modular-export.js
let stu={
name:"lily",
age:18
}
// 默认导出 一次导出一个数据 一个js里只能用一次
export default stu;
// 可以一次性导出多份数据
let num=100;
function say(){
console.log("hello");
}
//不需要用到default
export {num,say};
//模块化 require
//方式1
module.export={
name:num
}
//方式2
exports.array=[0,1]
require和import的区别:
- import特点:语句适用语法,使用在语句最顶层,编译时引入,异步引入,模块化导入,节省内存;浏览器具有缓存,运行效率提高
- require特点:函数调用的语法,可以实现按需引入,放在任何语句块都可以,运行时引入,同步引入(会阻塞其他资源)
打包项目
-
新建文件夹
-
初始化项目cnpm init -y
-
写代码 src .js
-
配置webpack.config.js
-
配置项目依赖 cnpm install webpack webpack-cli --save-dev
-
配置css依赖 cnpm i style-loader css-loader --save-dev
配置img依赖 cnpm i file-loader --save-dev
配置html依赖 cnpm install --save-dev html-webpack-plugin
配置清理/dist文件夹 cnpm install clean-webpack-plugin --save-dev
配置css整理 cnpm install --save-dev style-loader css-loader mini-css-extract-plugin
(两个css只能使用一个)
-
配置热服务更新 cnpm install --save-dev webpack-dev-server
-
运行命令(项目打包)webpack --watch
//在js文件中引入css文件
import"../css/index.css";
//webpack.config.js
//配置清理/dist文件夹的插件
const {CleanWebpackPlugin} = require('clean-webpack-plugin'); //添加到最前边!!
//配置整理css文件夹
const MiniCssExtractPlugin=require("mini-css-extract-plugin")
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports={
//配置js
//入口 输出路径
entry:"./src/js/main.js",
//出口 文件名+新文件名
output:{
path:__dirname+"/dist",
filename: '[name].[hash:6].js'
//filename:"bundle.js"
// filename:"[name].js"
},
//development开发模式,默认是production生产模式
mode:"development",
//loader
//配置css
module:{
rules:[
//内联引入配置css css-loader要放在style-loader后面
//{test:/\.css$/,use:["style-loader","css-loader"]},
//配置img
{test:/\.(png|jpg|gif|svg|jifi|webp|jpeg|bmp)$/,use:["file-loader"]}
//外联引入配置css2 css和css2只能有一个
{
test: /\.css$/,//正则表达式不要加igm 属性,影响loader 的多次匹配
use: [
MiniCssExtractPlugin.loader,//以<link>标签href 属性的形式实现外联引入,手动
// 'style-loader',//以<style>标签的形式引入在html 页内,只能与上面方式二选一
'css-loader'//解析css-loader必须要有,且放在数组第二项
]
}
]
},
//插件plugins
//配置html
plugins:[
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename:'./css/[hash:6].css'
}),
new HtmlWebpackPlugin({
hash:true, //为所有包含的脚本和CSS文件附加唯一的编译哈希,这对缓存清除很有用
filename: 'index.html', //打包后生成的文件名 放在output.path里面
template: './src/index.html', //来自哪里 模板文件
// index.html 里不需要引入js
inject: 'body', //引入js的位置:引入js的位置: 'head'-头部引入 'body'/true--</body>之前引入 false不引入
minify: { //压缩项配置
removeComments: true, //是否清除HTML注释
collapseWhitespace: true, //是否压缩HTML
removeScriptTypeAttributes: true, //是否删除< script>的type="text/javascript"
removeStyleLinkTypeAttributes: true, //是否删除< style>和< link>的type="text/css"
minifyJS: false, //是否压缩页内JS
minifyCSS: true //是否压缩页内CSS
}
})
],
//热服务更新的配置
//打包不会产生磁盘文件 打包完毕直接加载到内存运行
devServer: {
contentBase:'./dist',
host: 'localhost',
compress: true,
// inline: true,
port: 8080,
open: true,
hot: true
},
}
配置图片
//main.js
import"../css/index.css";
import basket from"./img/basket.jpeg";
console.log("hello")
var box=document.createElement("div")
box.innerHTML="hello world"
box.className="box"
document.body.appendChild(box)
var img=document.createElement("img")
img.src=basket
document.body.appendChild(img)
用npm运行
//package.json
{
"name": "mypro",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
//加入配置
"build": "webpack",
"watch": "webpack --watch",
//使用时使用 npm run build/watch即可
//加入热服务配置
//npm run dev 可以直接运行开发服务器
"dev": "webpack-dev-server --open --inline --progress --config webpack.config.js",
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^4.2.1",
"file-loader": "^6.0.0",
"html-webpack-plugin": "^4.3.0",
"style-loader": "^1.2.1",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12"
}
}
面试题
webpack 与gulp 工具的区别
-
webpack偏向于模块化开发的思想,gulp偏向于面向过程开发模式
-
webpack适用于大型复杂的前端站点构建,gulp 轻量级
loader和plugins的区别
-
loader:转换文件类型,对于不识别的文件类型进行编译打包。安装+module>rules配置
-
plugins:对打包之后的文件进行压缩优化清理 安装+引入+plugins配置
loader:
配置css依赖 cnpm i style-loader css-loader --save-dev
配置img依赖 cnpm i file-loader --save-dev
配置css整理 cnpm install --save-dev style-loader css-loader mini-css-extract-plugin
plugin:
CleanWebpackPlugin MiniCssExtractPlugin HtmlWebpackPlugin
devServer(热服务更新)和静态打包的区别:
静态打包会产生磁盘文件(存在C、D盘之类的)
devServer打包完毕直接加载到内存运行
webpack打包过程(构建流程):
- 初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置结果;
- 开始编译:上一步得到的参数初始化compiler对象,注册所有配置的插件,插件监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的 run 方法开始执行编译;
- 确定入口:从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去;
- 编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
- 完成模块编译并输出:递归完事后,得到每个文件结果,包含每个模块以及他们之间的依赖关系,根据entry或分包配置生成代码块chunk;
- 输出完成:输出所有的chunk到文件系统;
注意:在构建生命周期中有一系列插件在做合适的时机做合适事情,比如UglifyPlugin会在loader转换递归完对结果使用UglifyJs压缩覆盖之前的结果。
1.读取命令
2.读取配置webpack.config.js
3.启动命令
4.读取入口文件(entry)
5.通过loader对文件进行转换,编译打包
(style-loader css-loader file-loader)
6.通过plugin对打包后的文件进行压缩清理优化
(htmlwebpackplugin cleanwebpackplugin cssminiwebpackplugin)
7.输出文件output