Webpack
Webpack 是一个前端的静态模块资源打包工具,能让浏览器也支持模块化。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
Webpack 核心主要进行 JavaScript 资源打包
如下图,它可以结合其他插件工具,将多种静态资源css、png、sass 分类转换成一个个静态文件,这样可以减少页面的请求。可集成 babel 工具实现 EcmaScript 6 转 EcmaScript 5 ,解决兼容性问题可集成 http 服务器可集成模块热加载,当代码改变后自动刷新浏览器 等等功能
webpack1 和 webpack2+ 版本变化很大,基本上推倒重来, webpack1 目前已经基本不用了。
webpack1 官网 https://webpack.github.io/
webpack2.x 英文官网 https://webpack.js.org/
webpack2.x 中文官网 https://webpack.docschina.org/
webpack2.x 指南文档:https://webpack.docschina.org/guides/
安装最新版本
npm install --global webpack
或者 安装特定版本
npm install --global webpack@<version>
默认情况下, 模块化 JS 浏览器不能识别,可通过 webpack 打包后让浏览器识别模块化 JS
全局安装 webpack@v4.35.2 与 webpack-cli@3.3.6
npm i -g webpack@v4.35.2
npm i -g webpack-cli@3.3.6
查看全局安装目录
npm root -g
配置环境变量
查看webpack的版本
webpack -v
webpack小试
第一步写一个bar.js
// nodejs里面的模块代码,web默认不识别,node模块化编程,导出一个函数
module.exports=function(){
console.log('我是bar模块')
}
第二步写一个main.js
var bar=require('./bar.js')
bar()
第三步写一个index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./js/main.js"></script>
</body>
</html>
第四步测试index
很显然web不能识别bar.js的代码,需要使用到webpack进行打包
我的VScode出了问题,但是在cmd下面却可以正常打包
引入新的打包的文件,并启动index.html
使用webpack命令打包
以前使用的命令
webpack ./js/main.js -o ./js/bunter.js
修改后的命令
webpack
在 webpack-demo2 目录下创建 webpack.config.js 配置文件,该文件与 src 处于同级目录
// 引用 Node.js 中的 path 模块,处理文件路径的小工具
const path = require("path");
// 1. 导出一个webpack具有特殊属性配置的对象
module.exports = {
// 入口
entry: './src/main.js', // 入口模块文件路径
// 出口是对象
output: {
// path 必须是一个绝对路径 , __dirname 是当前js的绝对路径:
D:\StudentProject\WebStudy\webpack-demo2
path: path.join(__dirname, './dist/'), // 打包的结果文件存储目录
filename: 'bundle.js' // 打包的结果文件名
}
}
和entry与output同级下添加一个mode组件,对应的三个打包方式
production:生产环境,打包后的js是压缩版的
development:开发环境,打包后的js不压缩,易读
将webpack由全局的打包转换成局部的打包
本地安装的时候,建议把 webpack 安装到 devDependencies 开发依赖 ( --save-dev ) 中,因为 webpack 只是一个打包工具,项目如果需要上线,上线的是打包的结果,而不是这个工具。
所以我们为了区分生产环境和开发环境依赖,通过 --save (生产环境)和 --save-dev (开发环境)来区分。
1、为了测试本地安装,先把全局安装的 webpack 和 webpack-cli 卸载掉
npm uninstall -g webpack
npm uninstall -g webpack-cli
2. 安装 webpack@v4.35.2 与 webpack-cli
cd d:\StudentProject\WebStudy\webpack-demo3
# 2. 初始化项目 `-y` 是采用默认配置
npm init -y
# 3. 安装 v4.35.2 ,不要少了 v
npm i -D webpack@v4.35.2
# 安装 CLI
npm i -D webpack-cli@3.3.6
使用npm init-v命令就会生成一个package.json的文件,
里面的scripts则是填入命令行
scripts": {
"show": "webpack -v",
"start": "node ./src/main.js",
"build": "webpack"
},
最后打包命令webpack也能用了
EcmaScript 6 Module规范导入导出非默认成员
bar.js写方法和变量
main.js导入的三种方法
webpack使用css-loader打包CSS资源
打包 CSS 资源
安装 style-loader 和 css-loader 依赖
首先安装相关 Loader 插件:
css-loader 是 将 css 装载到 javascript;
style-loader 是让 javascript 认识 css。
npm install --save-dev style-loader css-loader
修改 webpack.config.js
// 引用nodejs里面的path模块,处理文件路径的小工具
const path = require("path")
// 导出一个有webpack具有特殊属性的对象
module.exports = {
// production 模式打包后 bundle.js是压缩版本的, development则不是压缩的,production这个是生产环境
mode: 'development',
entry: './src/main.js',//入口的文件路径
output: {//文件的出口
// path必须是一个绝对路径,__dirname 是当前js的绝对路径
path: path.join(__dirname, './dist/'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
//顺序不要写错了
'style-loader',//js转化成css
'css-loader'//css转化为js
]
}
]
}
}
注意点
这一块是配置的webpack.config.js里面的打包css的代码
注意: test: /\.css$/,这个没有单引号,这个是一个正则表达式,如果放单引号就成了字符串
module: {
rules: [
{
test: /\.css$/,
use: [
//顺序不要写错了
'style-loader',//js转化成css
'css-loader'//css转化为js
]
}
]
}
添加css文件
建立一个css文件夹,并创建一个style.css文件
body {
background:red
}
在main.js中引入css
通过npm run build 自定义命令进行打包
查看index.html
就是全红色背景
webpack打包图片
官网资料https://webpack.docschina.org/guides/asset-management/#加载-images-图像
安装 file-loader 依赖
npm install --save-dev file-loader
webpack.config.js里面添加打包图片的插件
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
修改style.css
body{
background: red;
background-image: url(./1.jpg)
}
打包编译
npm run build
问题
如果直接访问根目录下的 index.html ,那么图片资源路径就无法访问到。
解决方案:就是把 index.html 放到 dist 目录中。
但是 dist 是打包编译的结果,而非源码,所以把 index.html 放到 dist 就不合适。
而且如果我们一旦把打包的结果文件名 bundle.js 改了之后,则 index.html 也要手动修改。
综合以上遇到的问题,可以使用一个插件: html-webpack-plugin 来解决。
如果出现打包后路径问题,图片没有展示出来,则把index.html移到相同的目录下面
使用 HtmlWebpackPlugin 插件
作用:解决文件路径问题
将 index.html 打包到 bundle.js 所在目录中
同时也会在 index.html 中自动的
安装插件
npm install --save-dev html-webpack-plugin
修改 webpack.config.js
plugins: [
new HtmlWebpackPlugin({
// 此插件作用是将 index.html 打包到 bundle.js 所在目录中,
// 同时也会在 index.html 中自动的 <script> 引入 bundle.js
// 注意:其中的文件名 bundle 取决于上面output.filename中指定的名称
template: './index.html'
})
],
最后打包,npm run install
实时重新加载
说明
问题:
每一次手动打包很麻烦,打包后还需要手动刷新浏览器。
解决:
采用 webpack 提供的工具: webpack-dev-server ,它允许在运行时更新所有类型的模块后,而无需手动打包和刷新页面,会自动打包和刷新页面。可以很大程度提高开发效率。
参考:https://webpack.docschina.org/guides/development/#使用-webpack-dev-server
下载插件
npm install --save-dev webpack-dev-server
配置webpack.config.js
// 实时重新加载
devServer: {
contentBase: './dist'
},
在package.json下面的script下面配置npm run dev的这个命令
第六章 Babel 浏览器兼容性
安装 Bable
npm install -D babel-loader @babel/core @babel/preset-env
配置webpack.config.js
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/, // 排除的目录
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'] // 内置好的转译工具
}
}
}
]
}
这样的配置后就不用考虑到兼容性问题了
使用Vue-Loader 打包Vue单文件组件
Vue打包一
.vue单文件组件格式如下,但是.vue的单文件组件浏览器不能识别,需要使用到Vue-Loader进行打包
<templete>
写入模板
</templete>
<script>
写js代码
</script>
<style>
写入样式
<style>
安装 vue-loader 和 vue-template-compiler 依赖
npm install -D vue-loader vue-template-compiler
手动配置webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
// ... 其它规则
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 请确保引入这个插件!
new VueLoaderPlugin()
]
}
Vue打包二
安装Vue模块
npm install vue
第一步index.html中添加Id="app"
第二步添加一个App.vue测试使用
<template>
<div><h1>jjjjjjjjj</h1></div>
</template>
<script>
</script>
<style>
</style>
第三步在main.js中引入App.vue模块和Vue操作代码
import Vue from 'vue/dist/vue.js'
import App from'./App.vue'
new Vue({
el:'#app',
template:'<App/>',
components:{
App
}
})
导入完整版的Vue.js的解决办法有两种
一、引入的时候,引入vue.js 的路径而不是直接的Vue
import Vue from 'vue/dist/vue.js'
new Vue({
el: '#app',
template: '<App />',
components: {App}
})
二、引入Vue,然后在webpack.config.js里面加入配置
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
template: '<App />',
components: {App}
})
module.exports = {
// 解析完整版 vue.js
resolve: {
alias: {
'vue$': 'vue/dist/vue.js'
}
}
}
总结
以上两种方法都可以解决。但是完整版比运行时 vue 大,性能不如运行时 vue。
2. 官方更推荐运行时 vue,因为 vue-loader 可以编译 .vue 文件,所以事实上是不需要 vue 的编译功能的,
只需要渲染功能即可。
3. 而 template 自身没有渲染功能,最终渲染底层都是通过 render 函数够实现的。如果写 template 属性,则需
要编译成 render 函数,这个编译过程对性能会有一定损耗。
4. 所以使用运行时 vue 通过 render 函数来渲染组件即可。
处理方法使用render函数
import Vue from 'vue'
// vue/dist/vue.js
import App from './App.vue'
new Vue({
el: '#app',
// vue-loder有编译功能没有渲染功能
// templete实质上没有编译和渲染功能, 而当前可以直接采用vue-loader进行编译
// 而渲染功能通过render函数进行渲染组件
// template:'<App/>',
// render:function(h) {//h是一个函数,这个函数用于渲染组件
// // 函数的返回值就是渲染的结果
// return h(App)
// },
// 箭头函数简写一
// render:h=> {
// return h(App)
// },
// 箭头函数简写2
render: h => h(App)
// 如果使用了render,下面部分其实就可以省略了,默认情况下就作为子组件
// components:{
// App
// }
})
组件的添加
添加Foo.vue组件
<template>
<div>
<h2>我是子组件</h2>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
h2{
color: gold;
}
</style>
其中< style scoped>表示在当前组件的样子的渲染
<template>
<div><h1>jjjjjjjjj</h1>
<h1>{{msg}}</h1>
<foo> </foo>
</div>
</template>
<script>
import Foo from'./component/Foo.vue'
export default{
data() {
return {
msg:'hello jianghaojei'
}
},
// template:选项不用写,因为上面的template标签代表当前的组件模板
components:{
Foo,
}
}
</script>
<style>
/* <style scoped>这个代表在当前的组件下面的Style有用 */
h1{
color: red;
}
</style>
模块热替换(HMR)
介绍
模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。
模块热替换无需完全刷新页面,局部无刷新的情况下就可以更新。
参考:https://webpack.docschina.org/guides/hot-module-replacement/
第一步安装:要安装了 webpack-dev-server 模块
第二部按照文档上面修改
// 引用nodejs里面的path模块,处理文件路径的小工具
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
//引入Vue打包的插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const webpack = require('webpack');
// 导出一个有webpack具有特殊属性的对象
module.exports = {
// production 模式打包后 bundle.js是压缩版本的, development则不是压缩的,production这个是生产环境
mode: 'development',
entry: './src/main.js',//入口的文件路径
output: {//文件的出口
// path必须是一个绝对路径,__dirname 是当前js的绝对路径
path: path.join(__dirname, './dist/'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
// title: '管理输出'
template: './index.html'
}),
// v-loader请确保引入这个插件!
new VueLoaderPlugin(),
//模块热加载
new webpack.HotModuleReplacementPlugin()
],
// 实时重新加载
devServer: {
contentBase: './dist',
hot: true
},
module: {
rules: [
{
// 注意这里不要使用单引号,这里是一个正则表达式
test: /\.css$/,
use: [
//顺序不要写错了
'style-loader',//js转化成css
'css-loader'//css转化为js
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
// 解决兼容性问题
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/, // 排除的目录
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'] // 内置好的转译工具
}
}
},
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
}
}
这样修改了哪里的内容,就局部的刷新,上面的localhost:8080这个是不用刷新的