Webpack
webpack其实是require.js和gulp的后端实现方案
webpack = require.js + gulp
webpack想做模块化和资源整理处理压缩
引用webpack中文文档图说明webpack做什么
webpack的原理
- 闭包的原理
- eval
定义模块
define() //require.js
module.exports //ES5
export //ES6
引入模块
require() //require.js
require() //ES5
import //ES6
安装
npm install webpack webpack-cli -g
全局里面会有一个命令webpack
本地再装一次
npm install webpack
配置文件
新建一份webpack.config.js
配置文件
四大概念
- 入口(entry)
- 出口(output)
- loader 专门处理各种类型文件的插件
- 插件(plugins) 专门帮你压缩重命名合并的插件
入口出口配置
项目结构
dist
src
katsuki.js
index.html
webpack.config.js
katsuki.js
console.log('katsuki');
webpack.config.js
const path = require('path'); //内置模块
const webpack = require('webpack'); //第三方模块
module.exports = {
//设置开发环境,这里不设置mode会有warning提示,不影响
mode: 'development',
// 输入
// 读取src文件夹的katsuki.js文件,把它交给webpack处理
// 相当于gulp.src("xxx")
entry: './src/katsuki.js',
// 出口
// 把上面入口文件经过处理后,把它导出到dist文件夹的bundle.js里面
// 相当于gulp.dest("xxxx")
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
entry和output是我们webpack的必选项
cmd执行
webpack
执行,生产出bundle.js文件,结果如图
index.html引入bundle.js本地运行,打印katsuki
<script src="dist/bundle.js"></script>
利用上述的做法,只需在html文件中引入bundle.js,其他依赖写到katsuki.js进行webpack打包,解决依赖问题,案例如下
项目结构
dist
imgs
katsuki.jpg
libs
utils.js
src
katsuki.js
style
katsuki.css
index.html
webpack.config.js
utils.js
module.exports = {
plus(num1, num2) {
return num1 + num2
}
}
katsuki.js
console.log('katsuki');
// 第三方模块,需要先npm install jquery
let $ = require('jquery');
console.log($);
// 自定义模块
let utils = require('../libs/utils.js');
console.log(utils.plus(10,8));
index.html
<script src="dist/bundle.js"></script>
loader配置
loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)
未在webpack.config.js配置loader,在上面的基础上添加下面语句并执行
katsuki.js
let img = require("../imgs/katsuki.jpg");
cmd
webpack
会出错,如图
webpack.config.js配置loader如下,参考loader配置规则文档
babel-loader
会将js中ES6写法转化为ES5写法
npm install babel-loader@8.0.0-beta.0 @babel/core @babel/preset-env
webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: './src/katsuki.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
// 插件规则
rules: [{
// 如匹配到图片格式使用url-loader处理
// npm install --save-dev url-loader
test: /\.(jpg|jpeg|png|gif)$/,
use: 'url-loader'
}, {
// 如匹配到样式
// npm install --save-dev style-loader和css-loader
test: /\.css$/,
use: ['style-loader', 'css-loader']
}, {
// 处理html文件
// npm install --save-dev html-loader
test: /\.(html|htm)$/,
use: ['html-loader']
}, {
test: /\.js$/,
// 除了node_modules|bower_components所有的js文件都用babel-loader处理
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}]
}
};
配置完再运行webpack,文件压缩完成。
插件(plugins)
要用插件时参考官方文档,这里只举例使用html-webpack-plugin
webpack.config.js
const path = require('path');
const webpack = require('webpack');
// 通过npm安装
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/katsuki.js',
output: {
path: path.resolve(__dirname, 'dist'),
使用[hash]命名打包的js文件,每次都生成不同的乱码值,每打包一次都是不同的js文件
避免缓存问题,更改一些文件后,由于浏览器有缓存文件,出现不变更情况。
filename: '[hash].js'
},
plugins: [
// 它作为打包之后生成的index.html模板,打包完成后在dist文件夹中
new HtmlWebpackPlugin({
template: './index.html'
})
]
};
npm方式导入vue问题
npm方式导入vue问题
npm install vue
katsuki.js
import Vue from 'vue'
new Vue({
el : "#katsuki",
data : {
name : 'katsuki'
}
})
katsuki.js
经过webpack
打包成bundle.js
,引入运行文件
run.html
<div id="katsuki">
<p>{{name}}</p>
<p v-text="name"></p>
</div>
<script src="./dist/bundle.js"></script>
当打开页面出现如图的错误时
由于下载的npm install vue
的package.json
中默认引入文件如图
这个文件比dist文件夹中vue.js少了100K,删除了模板方法template,不能用{{}} v-text写法
方案一:render函数法创建元素
katsuki.js
import Vue from 'vue'
new Vue({
el : "#katsuki",
// 生成结果 <div>katsuki desu</div>
render(createElement) {
return createElement(
// createElement的第一个参数标签名称
'div',
// createElement的第二个参数是空对象,里面放属性值style、attr、on等
{
style: {
color: 'pink',
fontSize: '18px'
},
},
// createElement的第三个参数是子元素数组
['katsuki desu']
)
}
})
方案二:目录中webpack.config.js
添加下面resolve
部分
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: './src/katsuki.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
alias: {
// 把所有的vue的依赖的路径改为vue/dist/vue.js
'vue': 'vue/dist/vue.js'
}
}
};
vue生命周期
四大生命周期:编译、挂载、更新、销毁
- created:要更改数据,在created之后更改,加载数据,ajax,jonp
- mounted:要更改节点,在mounted之后更改,并且最好配合ref,ref改虚拟DOM
- updated:数据变动或者视图变动的时候可以用updated来监听 和watch和computed很相似
- beforeDestroy:节点销毁就会出beforeDestroy生命周期
除了beforeCreate和created,其他的before是虚拟DOM变,ed是真实DOM变
vue结合webpack(低阶组件化)案例
假设基于npm安装webpack、vue环境的项目结构
而且cmd执行webpack在dist生成use.js打包后bundle.js
dist
src
components
Xkatsuki.js
use.js
index.html
webpack.config.js
Xkatsuki.js
import Vue from 'vue'
let Xkatsuki = Vue.component("Xkatsuki", {
data(){
return {
name:"katsuki"
}
},
template : `
<div>
<p ref="katsuki" v-text="name"></p>
</div>
`,
// 以登台表演为例解释生命周期
// 上台前
// 毫无准备
// 没数据 没模板
beforeCreate() {
console.log("beforeCreate")
console.log(this.$data)
console.log(this.$el)
},
// 背台词,化妆
// 有数据,没模板
created() {
console.log("created")
console.log(this.$data)
console.log(this.$el)
},
// 没登舞台
// 有数据,有模板 模板还没挂载到DOM结构上
beforeMount() {
console.log("beforeMount")
console.log(this.$data)
console.log(this.$el)
},
// 登上舞台
// 模板 = > DOM 真正拿到DOM结构
mounted() {
console.log("mounted")
ref和$refs
// 利用html中没有的属性值,命名为ref,如
// <div ref="katsuki">666</div>,左侧对应命名,右侧非关键字即可
// $refs为所有含ref属性标签的存储对象
console.log(this.$refs)
// 通过这种方式设置样式来避免直接操作DOM结构
// jQuery方式 $(this.$refs.katsuki).css()
this.$refs.katsuki.style.color='pink'
console.log(this.$data)
console.log(this.$el)
},
// 表演前 虚拟DOM模板更新
// 数据更新了 模板更新了 但真实DOM结构没更新
beforeUpdate() {
console.log("beforeUpdate")
console.log(this.$data.name)
console.log(this.$el)
},
// 表演时候 更新真实DOM
// 数据更新了 模板更新了 真实DOM也更新
updated() {
console.log("updated")
console.log(this.$data.name)
console.log(this.$el)
},
// 谢幕前
beforeDestroy() {
console.log("beforeDestroy")
console.log(this.$data.name)
console.log(this.$el)
},
// 谢幕后
destroyed() {
console.log("destroyed")
console.log(this.$data.name)
console.log(this.$el)
}
})
export default Xkatsuki
use.js
import Vue from 'vue'
import Xkatsuki from './components/Xkatsuki.js'
new Vue({
el: "#demo",
template: `
<div>
<Xkatsuki></Xkatsuki>
<Xkatsuki></Xkatsuki>
</div>
`
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="demo"></div>
<script src="./dist/bundle.js"></script>
</body>
</html>
vue的单文件组件
.vue文件
本身不被浏览器识别,需要经过webpack
将所有的.vue文件
打包压缩后生成一个html文件
的操作组件化开发。
创建一个.vue
后缀的文件,如Xkatsuki.vue
,哪里用 <Xkatsuki />
就import到对应文件import Xkatsuki from 'Xkatsuki.vue文件路径'
Xkatsuki.vue
假设获取的data数据为json数据格式,内含多个这样的对象
{
title : xxx,
content : xxx
}
假设含该组件的项目服务器与数据服务器分离
<template>
<!-- View -->
<div>
<a
v-for="(d,index) in datas"
:key="index"
href="javascript:void(0);"
>
<h3 v-text="d.title"></h3>
<p v-text="d.content"></p>
</a>
</div>
</template>
<script>
export default {
// Model
data() {
return {
// 存放数据
datas: []
};
},
methods: {
// 下方描述vue中的async和await问题
// 获取数据的方法
async getDatas() {
// 出现跨域问题,参考之前的Node_express博文
let data = await this.$axios.get("https://katsuki.com?xxx json数据链接");
this.datas = this.datas.concat(data);
}
},
created() {
// 触发getDatas方法
this.getDatas();
}
};
</script>
<style scoped>
/*
含scoped,只作用当前组件样式,不含影响全局
不含scoped,为全局样式
webpack打包实现局部样式原理:
给当前组件的 div(根节点)添加 data-xxx自定义属性
利用css的属性选择器实现局部样式 div[data-xxx]
*/
</style>
async/await问题
webpack的babel本身不支持async/await
需要安装
npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime
在webpack
文件夹目录新增一个. babelrc
,这份是babel
配置文件
然后在里面写入
{
"plugins": ["transform-runtime", "babel-plugin-transform-regenerator", "babel-plugin-transform-es2015-modules-commonjs"]
}
把webpack
的use里面的options注释掉
{
test: /\.js$/,
// 除了node_modules|bower_components所有的js文件都用babel-loader处理
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
}
}