Long long ago…
当编写一个web网页时,
是这样来做↓↓↓
1.创建一个.html文件
2.引入对应的js逻辑模块
(面向过程方式)
// index.html
<body>
<div id="root"></div>
<script src="./index.js"></script>
</body>
//index.js
var dom = document.getElementById('root')
var header = document.createElement('div')
header.innerText = 'header'
dom.append(header)
var content = document.createElement('div')
content.innerText = 'content'
dom.append(content)
But…
当大前端技术的发展,js能实现的功能越来越多的时候,所有逻辑都会堆到一个js文件,这个js文件就会越来越大
So…
面向对象编程出现了↓↓↓
//index.js
// ES Moudule模块引入方式
import Header from './header.js'
import Content from './content.js'
//构造函数
new Header();
new Content();
//header.js
function Header() {
var dom = document.getElementById('root')
var header = document.createElement('div')
header.innerText = 'header'
dom.append(header)
}
export default Header
//content.js
function Content() {
var dom = document.getElementById('root')
var content = document.createElement('div')
content.innerText = 'content'
dom.append(content)
}
export default Content
运行后↓↓↓
╮(╯▽╰)╭╮(╯▽╰)╭╮(╯▽╰)╭╮(╯▽╰)╭
Why???
浏览器无法识别import 语法
解决办法:
webpack:
1.安装node
2.npm init //初始化包.创建package.json文件
3.npm install webpack-cli --save-dev //安装webpack-cli
4.npm install webpack --save //安装webpack
5.修改index.html中引入路径
<body>
<p>这是网页</p>
<div id="root"></div>
//<script src="./index.js"></script>
<script src="./dist/main.js"></script>
</body>
6.npx webpack ./index.js //使用webpack翻译index.js,生成dist包
OK!!!
所以,webpack拥有部分js代码翻译特性
一.是什么?
EN:webpack is a module bundler.
CN:webpack 是一个模块打包器。
二.搭建webpack环境
1.安装node.js(建议安装最新稳定版本)
2.npm init(初始化项目,生成package.json文件)
3.npm install webpack webpack-cli -g (全局安装webpack webpack-cli ,当多个项目webpack版本号不同时,不建议使用全局安装)
4.npm uninstall webpack webpack-cli -G(删除全局安装的webpack webpack -cli)
5,.npm install webpack webpack -D(项目内安装webpak webpak-cli,强烈推荐)
注意:项目内安装成功后,运行webpack -v 会报错,因为webpack -v命令是进行全局查找webpack,但是次时的webpack是安装在项目内,可用npx webpack -v查看版本号(npx会在当前目录下的node_moduies中查找webpack)
附:1.npm init -y (生成默认配置) 2.npm info webpack (查看webpack版本信息)
三.webpack配置文件
1.添加webpack,config.js文件(默认名称,可以通过 npx webpack --config 名称 修改默认名称)
2.修改配置
//webpack.config.js
const path = require('path');
// CommonJS语法
module.exports = {
//entry: {
// main: "./src/index.js"
//}
entry: "./index.js", //简写,开始打包的文件
output: {
filename: 'bundle.js', //打包后的文件名字
path: path.resolve(__dirname, 'bundle'), //打包后文件位置(绝对路径,注意需要引入webpack核心模块path,通过path.resolve(__dirname, '打包文件夹名称'),__dirname:webpack.config.js所在当前目录路径)
}
}
打包流程:1.运行npx webpack→2寻找配置文件(webpack.config.js)→3根据配置文件完成打包
3.通过npm scripts方式打包
//package.json
"scripts": {
"bundle":"webpack", //运行npm run bundle命时,自动执行webpack命令
}
运行npm run bundle:
警告信息提示没有配置mode:
再次打包:
Perfect !!!
四.Loader
之前我们打包的文件都是.js文件,当我们打包jpg文件时↓↓↓
原因:webpack默认只认识.js文件,不知道jpg文件如何打包
办法:
1.添加webpack.config.js配置项
//webpack.config.js
module: { //打包模块
rules: [ //规则,数组类型
{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'file-loader',
options: { //额外参数
name: '[name]_[hash].[ext]', //placeholder 占位符
outputPath: 'images', //打包后文件存放的位置
}
}
}
]
}
2.npm install file-loader -D (下载 file-loader插件)
3.运行npm run bundle进行打包
OK!!!
那么,如何知道当打包jpg文件时使用file-loader呢?
点这→文档→LOADER→file-loader
Loader:是一种打包的方案,对于特定的文件进行特定的处理
五.plugins
1.下载HtmlWebpackPlugin插件并安装(地址)
HtmlWebpackPlugin会在打包结束后,自动生成一个html文件,并把打包生成的js文件自动引入到这个html文件中
运行生成的html文件↓↓↓
修改webpack.config.js
//webpack.config.js
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html' //以指定路径下的html文件生成打包后的html文件
})]
plugin:可以在webpack运行到某个时刻的时候,做一些事情(类似于vue中生命周期函数)
查看更第三方plugin请点击这里
六.Entry与Output
在第三章中,entry编写的是入口文件,当想同一个文件打包两次的时候↓↓↓
//webpack.config.js
entry: {
main: './src/index.js',
sub: './src/index.js'
},
运行↓↓↓
打包成功,但是查看项目目录时,只有一个bundle.js文件
因为
解决:
//webpack.config.js
output: {
filename: '[name].js', //打包后的文件名字
},
运行打包命令:
而打包后的index.html中
那么,又双叒叕有问题了,我们会把打包完的index.js文件给后端,作为一个后端入口文件,但是会把js文件上传到cdn,那么打包生成index.html中script标签的src就需要变成拥有cdn地址的域名(如:src=“http://cdn/sub.js”)↓↓↓
//webpack.config.js
output: {
publicPath: 'http://cdn'
},
运行打包命令↓↓↓
更多output配置项,点这里
七.SourceMap
SourceMap:是一种映射关系,打包后文件所对应打包前代码的位置
//webpack.config.js
devtool: 'source-map',
// inline: .map文件直接打包到main.js文件中
// cheap: 只告知第几行出错, 不告知第几列
// module: 业务代码 + 第三方模块报错
// eval:通过evel的执行形式,生成对应关系
//开发环境(development)推荐:cheap-module-eval-source-map
//线上环境(production)推荐:cheap-module-source-map
更多配置点这里
八.webpackDevServer
编辑完代码后自动打包并执行
1.自动实现打包
//package.json
"scripts": {
"watch": "webpack --watch"
}
2.WebpackDevServer(监听文件自动打包,自动刷新浏览器,自动打开浏览器),强烈推荐!!!
1.npm install webpack-dev-server -D(安装webpack-dev-server)
2.
//webpack.config.js
devServer: {
contentBase: 'dist', //告诉服务器从哪个目录中提供内容,绝对路径
open: true //自动打开浏览器
},
//package.json
"scripts": {
"start": "webpack-dev-server"
},
注意:devServer方式,打包后会默认通过类似于http://localhost:8080方式在浏览器中打开,这种方式是为了方便进行ajax请求,而通过file协议打开,不便发送ajax请求
更多devServer配置,点击这里
3.自己搭建,第三方插件
//package.json
"scripts": {
"middle":"node server.js"
},
2.根目录下手动创建server.js文件(注意名称和scripts中的名称保持一致)
3.终端安装查件,npm install express webpack-dev-middleware -D
express :点击
webpack-dev-middleware:点击
4.修改配置
//webppack.config.js
output: {
publicPath: '/', //所有打包生成的文件引用前都添加一个跟路径,确保打包的文件不会有路径问题
}
5.编写server.js文件
//server.js
const express = require('express')
const webpack = require('webpack')
//创建服务器实例
const app = express()
//监听端口,服务器启动成功打印ok
app.listen(3000, () => {
console.log('Ok')
})
运行npm run middle↓↓↓
继续编写server.js文件
//server.js
//在node中使用webpack
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const config = require('./webpack.config.js')
// webpack编译器,便于随时进行代码编译
const complier = webpack(config);
//创建服务器实例
const app = express()
//通过use()使用app实例的webpackDevMiddleware中间件
//webpackDevMiddleware(编译器,{配置项})
//当文件发生改变,使用配置项打包编译
app.use(webpackDevMiddleware(complier, {
publicPath: config.output.publicPath
}))
//监听端口,服务器启动成功打印ok
app.listen(3000, () => {
console.log('Ok')
})
运行npm run middle↓↓↓
九.HMR热模块更新
新建number.js和button.js,编写index.js
//number.js
function number() {
// 创建div标签
var div = document.createElement('div')
div.setAttribute('id', 'number')
//div内容为1000
div.innerHTML = 1000
// 将div挂载到body上
document.body.appendChild(div)
}
export default number
//button.js
function button() {
// 创建div标签
var div = document.createElement('div')
//定义变量,初始值为0
var i = 1
div.innerHTML = i
//div添加点击事件
div.onclick = function () {
//div内容为i++
div.innerHTML = i++
}
// 将div挂载到body上
document.body.appendChild(div)
}
export default button
//index.js
import number from './number'
import button from './button'
number()
button()
运行npm run start打包编译,点击数字1,浏览器效果↓↓↓
修改index.js文件代码,将2000更改为1000
//index.js
div.innerHTML = 2000
保存后,重新打包,页面刷新,之前的点击按钮,i++的效果消失↓↓↓
如何解决这个问题呢↓↓↓
//webpack.config.js
//引入webpack
const webpack = require('webpack')
devServer: {
hot: true, //开启Hot Module Replacement
hotOnly: true //不让浏览器自动刷新
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
//index.js
import number from './number'
import button from './button'
button()
number()
// Hot Module Replacement是否为true
if (module.hot) {
//监听number.js
module.hot.accept('./number', () => {
document.body.removeChild(document.getElementById('number'))
number()
})
}
运行效果如下
修改number.js中数值1000
//number.js
div.innerHTML = 2000
运行结果↓↓↓
更多HMR配置,点击这里
十.Babel处理ES6
在index.js中编写es6代码
const arr = [
new Promise(() => { }),
new Promise(() => { })
]
npm run start打包运行
谷歌浏览器↓↓↓
IE浏览器↓↓↓
出现兼容bug,此时就需要将es6语法转换成es5的语法(babel)
1安装babel
https://www.babeljs/setup#installation
2.运行npx webpack打包,查看打包后的main.js文件
成功将es6语法转化成es5语法
3.但是其中的一些map方法,在一些低版本浏览器中还是没有,也就是说,只是做了一部分转化,或者是只兼容了一部分浏览器,那如何兼容那些浏览器呢?
polyfill
打包运行后
IE浏览器↓↓↓
兼容成功!!!
当然,在开发第三方模块或者是在开发一个类库时@babel/polyfill会存在一些问题,因为在注入一些es6的属性时,是通过全局变量的形式,会污染全局环境
1安装.@babel/plugin-transform-runtime(闭包形式引入组件内容)
2.修改配置项
//webpack.config.js
module: { //打包模块
rules: [ //规则,数组类型
{
test: /\.m?js$/,
exclude: /node_modules/, //如果代码存在node_nodules中
use: {
loader: "babel-loader",
options: {
"presets": ['@babel/preset-env'],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": 2, //当修改core.js时需要重新安装npm install --save @babel/runtime-corejs2
"helpers": true,
"regenerator": true,
"version": "7.0.0-beta.0"
}
]
]
}
}
}
]
},
打包↓↓↓
十一.配置react代码打包
1安装react(npm install react react-dom --save)
2.编写index.js
import "@babel/polyfill";
import React, { Component } from "react";
import ReactDOM from "react-dom";
class APP extends Component {
render() {
return (<div>hellon world</div>)
}
}
ReactDOM.render(<APP />, document.getElementById('root'))
运行npm run start,打包编译👇👇👇
报错!!!
∴使用babel+webpack无法打包react代码
3.安装@babel/preset-react,修改配置
//webpack.config.js
module: { //打包模块
rules: [ //规则,数组类
{
test: /\.m?js$/,
exclude: /node_modules/, //如果代码存在node_nodules中
use: {
loader: "babel-loader",
options: {
"presets": ["@babel/preset-react"],
}
}
}
]
},
打包运行:
成功!!!
gitHub:https://github/666cwh/webpack
webpack:https://v4.webpack.docschina/
babel:https://babeljs.io/
更多推荐
webpack
发布评论