学习 https://juejin.im/post/5cecd6fdf265da1b827a7ca5
一直都是直接vue-cli脚手架搭起来的,没怎么自己动手玩过webpack,这次就简单的玩一下~~ 开心
安装
$ npm install webpack webpack-cli -D 或者 npm install webpack webpack-cli --save-dev
起步
npm init -y
生成package.json配置文件
添加基础代码
- index.html
<body>
<p>这是最原始的网页内容</p>
<div id="root"></div>
<script src="./dist/main.js"></script>
</body>
- index.js
console.log('hello, world')
- 通过指令
touch webpack.config.js
新建该文件 - 编辑webpack.config.js文件
const path = require('path')
module.exports = {
entry: './index.js',
output: {
filename: 'main.js',
// path配置了打包后的输出目录为dist文件下
path: path.resolve(__dirname, 'dist')
}
}
- 改写package.json文件
- 添加
private
属性并设置为true
,此属性能让我们的项目为私有的,防止意外发布代码 - 移除
main
属性,我们的项目并不需要对外暴露一个入口文件 - 添加
scripts
命令,即我们的打包命令
{
"name": "webpack",
"version": "1.0.0",
"description": "",
"private": true,
"dependencies": {
"webpack-cli": "^3.3.7",
"webpack": "^4.39.3"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"bundle": "webpack" // 打包命令
},
"keywords": [],
"author": "",
"license": "ISC"
}
- 运行以下命令对项目进行打包
npm run bundle
打包成功后,项目目录下就会多出一个dist文件夹,文件夹下有main.js文件
打包静态资源
什么是loader?
loader是一种打包规则,它告诉了Webpack在遇到非js文件时,应该如何处理这些文件
loader有几种固定的运用规则
- 使用test正则来匹配相应的文件
- 使用use来添加文件对应的loader
- 对于多个loader而言,从右到左以此调用
使用loader打包图片
打包图片需要用到file-loader 或 url-loader
npm install file-loader -D
添加打包图片规则
在webpack.config.js
文件下添加打包图片规则
module.exports = {
module: {
rules:[
{
test: /\.(png|jpg|git)$/,
use: {
loader: 'file-loader'
}
}
]
}
}
- 打包后的项目目录
2.png这个图片打包到了dist下
运用占位符
从上面的截图可以看得到,打包生成的图片的命名是一堆乱码,如果我们要原样输出原图片的名字的话,又该如何配置呢?
使用占位符进行解决
- [name] 代表原本文件的名字
- [ext] 代表原本文件的后缀
- [hash] 代表一个唯一编码
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name]_[hash].[ext]'
}
},
}
]
}
编译成功后,打包成功的文件命名如下
使用loader打包CSS
样式文件分为几种情况,每一种都需要不同的loader来处理
- 普通
.css
文件,使用style-loader
和css-loader
来处理 .less
文件,使用less-loader
来处理.sass或者.scss
文件,需要使用sass-loader处理.styl
文件,需要使用style-loader
来处理
添加css,并打包
-
根目录下添加index.css文件
.avatar { width: 50px; height: 50px; }
-
修改index.js
// 引入index.css文件
...
import './index.css'
var img = new Image()
...
打包文件
打包Sass文件
需要安装sass-loader和node-sass (scss/sass都可以用sass-loader打包)
npm install sass-loader node-sass -D
sass的语法格式是一种缩进格式;scss类似于css,大括号格式
- 添加index-scss.scss文件
body {
.avatar-scss{
width: 100px;
height: 100px;
}
}
- 修改index.js
...
import('./index-scss.scss')
img.classList.add('avatar-scss')
打包成功
自动添加css厂商前缀
当我们在css文件中写一些需要处理兼容性的样式的时候,需要我们分别对于不同的浏览器添加不同的厂家前缀。可以使用postcss-loader
在webpack打包的时候自动添加这些厂家前缀
自动添加厂家前缀需要npm install
安装postcss-loader
和autoprefixer
npm install postcss-loader autoprefixer -D
- webpack.conf.js下添加postcss-loader
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader'] //从右向左顺序调用,所以顺序不可以错
}
- index.css下添加需要处理兼容性样式
...
transform: translate(50px, 50px)
- 根目录添加 postcss.config.js
module.exports = {
plugins: [require('autoprefixer')]
}
进行打包
!!!! 这里蛮奇怪的,打包好了,感觉很成功的,但是控制台没有显示…是我对控制台的理解不够深刻吗?
模块化打包css文件
- 新建一个createAvatar.js
import avatar from './1.png'
export default function createAvatar () {
var img = new Image()
img.src = avatar
img.classList.add('avatar-scss')
var root = document.getElementById('root')
root.appendChild(img)
}
- 在index.js下引入这个方法
import createAvatar from './createAvatar.js'
createAvatar()
打包效果
发现引进来的方法,会受index下引入的css文件的影响,那么能否消除这个影响呢? 需要开启对css样式文件的模块打包
- 修改webpack.config.js文件
[外链图片转存失败(img-muZocsmY-1567437934387)(D:\2019.5月秋招准备\面试题\项目记录\4.png)]
- 修改完成后需对index.js作改动
import style from './index-scss.scss'
img.classList.add(style['avatar-scss'])
打包
avatar下的图片没有受到index下css影响,显示了自己最原本的样子
webpack核心
使用WebpackPlugin
plugin 当webpack运行到某一个阶段,使用plugin来帮我们做一些事情
- 进行一系列改动 删除不必要文件与移动文件
- 修改index.js文件
var root = document.getElementById('root')
var dom = document.createElement('div')
dom.innerHTML = 'hello, world'
root.appendChild(dom)
- 修改webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
// path配置了打包后的输出目录为dist文件下
path: path.resolve(__dirname, 'dist')
}
}
html-webpack-plugin
html-webpack-plugin
可以让我们使用固定的模板,在每次打包的时候自动生成一个.html文件,并且它会自动帮我们引入打包后的.js文件
安装
npm install html-webpack-plugin -D
- 在src目录下新建index.html文件
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>HTML模板</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="root"</div>
</body>
</html>
- 使用html-webpack-plugin 修改webpack.config.js文件
// 引入该plugin
const htmlWebpackPlugin = require('')
module.exports = {
... 其他代码
plugins: [
new htmlWebpackPlugin({
//使用固定的模板解析index.html
template: './src/index.html'
})
]
}
打包完成后 dist/index.html 会引入js文件 这是这个plugin帮我们实现的
clean-webpack-plugin
clean-webpack-plugin
可以帮我们在打包之前自动删除dist打包目录下的所有文件,不用我们手动删除
SourceMap
良好的source-map配置不仅n能帮助我们提高打包速度,同时在代码维护和调错方面也有很大的帮助,一般来说,sourcemap的最佳实践如下
- 开发环境下(
development
):推荐将devtool
设置成cheap-module-eval-source-map
- 生产环境下(
production
):推荐将devtool
设置成cheap-module-source-map
使用WebpackDevServer
webpack-dev-server可以帮助我们在源代码更改的情况下,自动帮我们打包我们的代码并启动一个小型的服务器。如果与热更新一起使用,它能帮助我们高校的开发
自动打包的方案,通常有以下几种
watch
参数自动打包,虽然能够帮我们自动打包,但我们仍然需要手动刷新浏览器,同时他不能够帮我们在本地启动一个小型服务器,一些http请求不能通过webpack-dev-server
插件打包(推荐): 他是我们推荐的一种自动打包方案,在开发环境下使用尤其能够帮我们高效的开发,它能解决watch参数打包中的问题,与热更新
watch参数自动打包
- 在package.json下
"scripts": {
... 其他代码
"watch": "webpack --watch"
}
- 运行
npm run watch
改变src/index.js中的innerHTML
刷新网页,发现其自动更新了
说明了watch可以实现自动打包的功能,但仍然要刷新
webpack-dev-server打包
要使用webpack-dev-server
,需要使用如下命令进行安装
npm install webpack-dev-server -D
- 在package.json中进行修改
"scripts": {
"watch": "webpack --watch",
"dev": "webpack-dev-server"
}
- 在webpack.config.js中进行修改
module.exports = {
... 其他代码
devServer: {
// 以dist文件为基础启动一个服务器,服务器运行在4200端口上,每次启动时自动打开浏览器
contentBase: 'dist',
open: true,
port: 4200
}
}
!!!!!!!!我好激动,原来vue-cli脚手架npm run dev后自动打开网页 并且修改代码后浏览器也会自动刷新是这样来的!!! 太开心拉~
模块热更新(HMR)
模块热更新的理解:它能够让我们在不刷新浏览器(或自动刷新)的前提下,在运行时帮我们更新最新的代码
模块热更新(HMR)已内置到 Webpack ,我们只需要在webpack.config.js
中像下面这样简单的配置即可,无需安装别的东西。
- 修改webpack.config.js
const webpack = require('webpack')
module.exports = {
devServer: {
contentBase: 'dist',
port: 4200,
open: true,
hot: true,
hotOnly: true
},
plugins: [
new Webpack.HotModuleReplacementPlugin()
]
}
css中的模块热更新
- 在style.css中添加代码
div:nth-of-type(odd) {
background-color: red;
}
- 改写src目录下的index.js中的代码
import './style.css'
var btn = document.createElement('buttom')
document.body.appendChild(btn)
btn.onclick = function () {
var dom = document.createElement('div');
dom.innerHTML = 'item';
document.body.appendChild(dom);
}
- 添加保留处理css文件的loader
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
npm run dev 打包
[外链图片转存失败(img-5k6TohLd-1567437934390)(D:\2019.5月秋招准备\面试题\webpack\7.png)]
理解: 由于item是动态生成的,当我们要将red
颜色改变成yellow
时,模块热更新能帮我们在不刷新浏览器的情况下改变样式的内容。
js中的模块热更新
- 在src目录下创建两个.js文件,
number.js
和counter.js
number.js
export default function number () {
var dom = document.createElement('div')
dom.setAttribute('id', 'number')
dom.innerHTML = '3000'
document.body.appendChild(dom)
}
counter.js
export default function counter () {
var dom = document.createElement('div')
dom.setAttribute('id', 'counter')
dom.innerHTML = 1
dom.onclick = function () {
dom.innerHTML = parseInt(dom.innerHTML, 10) + 1
}
document.body.appendChild(dom)
}
- 添加完以后,对index.js文件做一下改动
import counter from './counter.js'
import number from './number.js'
counter()
number()
打包完成后,使用npm run dev打包,在页面上点击数字1,累加到一定数值。修改number.js下的初始值1000->3000 ,会发现,网页上,1000成功变成了3000,但是累计的数值却重置成1。
- 对js代码进行额外的模块HMR配置 index.js
if (module.hot) {
module.hot.accept('./number.js', () => {
document.body.removeChild(document.getElementById('number'))
number()
})
}
这样修改number.js下的number值后,累计的数值就不会发生改变~~
处理ES6语法
我们在项目中书写的ES6代码,由于考虑到低版本浏览器的兼容性问题,需要把ES6代码转换成低版本浏览器可以识别的ES5代码。使用babel-loader
和@babel/core
来进行ES5和ES6之间的链接,使用@babel/preset-env来进行ES6转为ES5