五个概念
五个概念:
- 入口entry
- 定义分析依赖的入口文件,类似于vue的main.js,从入口文件开始解析文件依赖关系,并将其打包
- 出口output
- 打包的产物,产出到哪里,以及产出的文件名
loader
- 针对某类型文件使用的转换。
module: {
rules: [
# 当碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时
# 在打包之前,先使用 raw-loader 转换一下
{ test: /\.txt$/, use: 'raw-loader' }
]
}
- 针对某类型文件使用的转换。
插件plugin
- 插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
- 模式
- 生产production时、开发development时
module.exports = {
mode: 'production'
};
从场景中学配置
webpack核心: 是一个模块打包器
和传统的html文件里手动引入各资源相比,html文件作为管理方;webpack将一切资源视为模块,在webpack这个炼丹炉里,模块之间可以相互调用,比如css文件引用css文件,js文件引用css文件
这种能力的实现使得我们可以在html上直接生成一个节点,之后的所有操作,都可以通过模块打包器,将代码引用的图片、css、js、dom整理好,直接挂载在这个节点上。最终页面得以呈现
期间我们解决了
- js文件相互引用的问题,而不是将所有js放到一个html文件里,有命名冲突和变量被直接修改的风险 (模块化)
- ide的代码变化浏览器就得以变化的livereload or hmr
- less
js文件的模块化
1、一个空文件夹,npm init 初始化后 添加以下配置
需要的条件:
# package.json
"scripts": {
"build": "webpack"
},
"devDependencies": {
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11"
}
2、按照如下文件结构,创建文件
├── dist
│ └── index.html # <script src="main.js"></script>
├── src
│ ├── index.js # 默认的根文件
│ └── print.js # index.js 引用了 print.js
└── package.json
3、开始打包 npm run build
就可以看到 /dist文件夹下面自动生成了main.js文件,该文件是以index.js为入口将其依赖的所有文件打包后生成的main.js(默认压缩)
以上便是最简单的一个入门使用了
但是和我们平时使用脚手架如vue等,对比起来我们还需要做的:
- 不依赖约定配置,自己定义入口出口文件 => entry\output字段
- html里引用打包后的js,能不能手动添加改为自动?即打包生成js后自动插入html中
=> plugin: HtmlWebpackPlugin
- dist文件只存在实际项目用到的,多余的每次打包时会清理掉
=> plugin: clean-webpack-plugin
- 管理资源:css的加载引用 => loader: style-loader\css-loader
- 开发时追踪错误和警告:devtool: ‘inline-source-map’
- 修改代码后自动编译打包:”watch”: “webpack —watch”,
- live reload打包文件变化后自动刷新浏览器:实时重新加载 webpack-dev-server
- 自己传入html而不是js生成html:new HtmlWebpackPlugin template \raw-loader
其中模块化的写法可以:
1、es6 export default import xxx from ‘xxxx’
2、node的commonjs require 、 module.exports
3、处理图片
// addImage.js
let smallImg = document.createElement('img')
# require 语法
smallImg.src = require('../images/small.jpeg')
document.body.appendChild(smallImg)
库:
- url-loader
4、处理css文件
import '../styles/addImage.css' # 控制图片大小的css
let smallImg = document.createElement('img')
smallImg.src = require('../images/small.jpeg')
document.body.appendChild(smallImg)
库:
- css-loader:让 CSS 文件也支持 import,并且会解析 CSS 文件
- style-loader:将解析出来的 CSS 通过标签的形式插入到 HTML 中
然而一股脑将css文件整合进js文件也是有弊端的,大量css文件会使得js变得臃肿
因此extract-text-webpack-plugin插件 可以将css文件打包为一个单独的文件
然后打包成单独的css文件之后 就 需要手动在html代码里 添加css的依赖,
所以需要插件 html-webpack-plugin , 将文件自动引入html里
module.exports = {
//...
plugins: [
// 我们这里将之前的 HTML 文件当做模板
// 注意在之前 HTML 文件中请务必删除之前引入的 JS 文件
new HtmlWebpackPlugin({
template: 'index.html'
})
]
};
进阶
思考的问题:
1、分块打包 ( 常改动的和不常改动的第三方库分开打包,给不常改动的添加浏览器缓存
2、抽取公共代码 ==> CommonsChunkPlugin插件
3、按需加载
bundle 文件包含了我们全部的自己代码。但是当用户访问我们的首页时,其实我们根本无需让用户加载除了首页以外的代码
所以需要分割代码,按场景。首页必须的,切换到某个页面再重新加载的。。
==> 这个优化我们可以通过路由的异步加载来完成。
4、自动刷新
webpack-dev-server
5、别名
module.exports = {
resolve: {
extensions: ['.js', '.css', '.json'],
// 路径别名,比如这里可以使用 css 指向 static/css 路径
alias: {
'@': resolve('src'),
'css': resolve('static/css')
}
},
// 生成 source-map,用于打断点,这里有好几个选项
devtool: '#cheap-module-eval-source-map',
}
一步步从零开始用 webpack 搭建一个大型项目
配wbpack最关键的是思路问题!为什么这样说呢?大家不会配,不是他因为他不会去查webpack和粘代码,更多的是他想不到,就是没整个工程化的思路
在**场景,我们遇到了什么样的问题,好,那我们需要怎么去处理它,然后最后一步是,来我教你配webpack
所以尽量 回溯到场景里 这样才能记住接口
webpack常用的loader、插件
- css-loader:让 CSS 文件也支持 import,并且会解析 CSS 文件
- style-loader:将解析出来的 CSS 通过标签的形式插入到 HTML 中
- babel-loader 用于让 webpack 知道如何运行 babel
- babel-core 可以看做编译器,这个库知道如何解析代码
- babel-preset-env 这个库可以根据环境的不同转换代码
- 抽取公共代码 ==> CommonsChunkPlugin插件
- html-webpack-plugin , 将文件自动引入html里
require 和 import 的区别
=> 解析 bundle 如何加载模块的、webpack 如何实现的动态加载模块
我们使用的 require
,是被 webpack
的api即webpack_require,打包之后产生的dist/bundle.js是一个立即执行函数,它是把所有模块捆绑在一起的一个巨型模块。
import:import 跟 require 的区别是,import 是动态加载只有在用到的时候才会去加载,而 require 只要声明了就会加载。
import原理:
import 去引用一个模块,除了正常的 bundle 之外,我们还可以看见一个 0.boundle.js(即动态加载的 index.css
模块)
动态模块加载逻辑:利用的 jsonp 的实现原理加载模块
参考资料
1、webpack:从入门到真实项目配置
2、一步步从零开始用 webpack 搭建一个大型项目
3、https://survivejs.com/webpack/foreword/