webpack

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.com/sub.js”)↓↓↓

//webpack.config.js
output: {
    publicPath: 'http://cdn.com'
  },

运行打包命令↓↓↓
在这里插入图片描述
更多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.cn/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.com/666cwh/webpack
webpack:https://v4.webpack.docschina.org/
babel:https://babeljs.io/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值