实战webpack4.0常用配置与优化_jquery

 

实战webpack4.0常用配置与优化_配置文件_02

 

注意:



1、在webpack里,所有文件都是模块
例如:JS模块--->模块化(AMD、CMD、ES6 Module、Commonjs)
  如下所示


  实战webpack4.0常用配置与优化_html_03

  接下来便可以导入使用

  实战webpack4.0常用配置与优化_配置文件_04

  最后做下验证输出,可以直接打包生成文件

  实战webpack4.0常用配置与优化_html_05

  接下来做下测试,引入脚本文件,打开html文件进行测试

  实战webpack4.0常用配置与优化_热更新_06

  但我们想知道这里为什么是main.js,接下来做个配置文件进行修改

  实战webpack4.0常用配置与优化_热更新_07

 

  接下来开始编写代码,但注意webpack是基于node的,所以必须遵循Commonjs规范

  实战webpack4.0常用配置与优化_html_08

  依次填充入口与出口文件

  实战webpack4.0常用配置与优化_jquery_09

 

 

  接下来进行打包测试,则如下所示

  实战webpack4.0常用配置与优化_热更新_10

 

 

  至此便可以实现自定义打包并验证,但不可能每次都需要自己新建html引入验证,所以我们可以在webpack引入服务,给其配置一个开发服务器。

  (1)接下来配置开发服务器webpack-dev-server

    1、首先进行安装

    实战webpack4.0常用配置与优化_css_11

 

 

    2、启动指令--npx webpack-dev-server,此时便可以在localhost:8000端口查看文件

    实战webpack4.0常用配置与优化_html_12

 

 

    3、为了方便使用指令,我们使用scripts字段设置命令简称

    实战webpack4.0常用配置与优化_热更新_13  

    此时执行npm run start或者npm start即可,结果如下

    实战webpack4.0常用配置与优化_配置文件_14

 

 

    4、打开指定文件,渲染到指定html文件,而不是文件目录界面

    分析如下,此时打开的是项目跟目录

    实战webpack4.0常用配置与优化_热更新_15

 

 

    所以我们需要配置开发服务器

    实战webpack4.0常用配置与优化_热更新_16

    测试如下,此时再次打开localhost:8000时便会直接到该目录

    实战webpack4.0常用配置与优化_html_17

 

 

    实战webpack4.0常用配置与优化_css_18

 

 

    5、配置开发服务器端口号、压缩文件、自启动

    实战webpack4.0常用配置与优化_html_19

    此时再运行便会自动打开浏览器的http:localhost:3000端口

    实战webpack4.0常用配置与优化_热更新_20

 

 

  (2)webpack插件plugins------动态添加html文件

    目前为止都是手动添加html文件,然后手动引入js文件,最后查看效果的... ...过于繁琐。

    因此我们换个思路,先将打包文件放到src的index.html里,然后再将整个打包

    实战webpack4.0常用配置与优化_热更新_21

    实战webpack4.0常用配置与优化_jquery_22

 

 

    1、下载依赖



>npm i html-webpack-plugin -D


    webpack使用插件有个共同点:即在使用前都必须用node语法即CommonJS语法导入.

    实战webpack4.0常用配置与优化_css_23

 

 

    2、编写打包指令缩写,进行打包

    实战webpack4.0常用配置与优化_配置文件_24

 

 

    接下来执行npm run build开始打包,结果如下

    实战webpack4.0常用配置与优化_热更新_25

    且里面自动引入了脚本文件js

    实战webpack4.0常用配置与优化_jquery_26

 

 

    3、添加其他参数:修改标题等(这里可以参考npm官方文档进行配置

    实战webpack4.0常用配置与优化_jquery_27

 

    实战webpack4.0常用配置与优化_jquery_28

 

 

    接着配置src/index.html文件,如下所示

    实战webpack4.0常用配置与优化_css_29

 

    接下来进行打包并启动服务,效果如下

 

    实战webpack4.0常用配置与优化_热更新_30

 

 

    实战webpack4.0常用配置与优化_jquery_31

 

 

    4、压缩html文件

    实战webpack4.0常用配置与优化_jquery_32

    加上hash后src文件会价格hash随机数值,避免缓存

    实战webpack4.0常用配置与优化_html_33

    实战webpack4.0常用配置与优化_jquery_34

 

 

    此外,也可以在src前面价格,随机src文件名,避免缓存

    实战webpack4.0常用配置与优化_html_35

 

 

    此时前后都有随机数,如下

    实战webpack4.0常用配置与优化_html_36

 

 

    此后每次打包都会产生新文件... ....,接下来配置下删除文件操作,此时需要用到另一个插件clean-webpack-plugin

  实战webpack4.0常用配置与优化_html_37

 

 

  1、首先安装依赖

    实战webpack4.0常用配置与优化_jquery_38

 

 

  2、引入插件依赖

    实战webpack4.0常用配置与优化_热更新_39

 

 

  3、开始使用

    实战webpack4.0常用配置与优化_配置文件_40

 

 

 

(3)多文件打包问题

  此时入口文件为src/index.js,我们打包时会查找与index.js相关联依赖的文件,例如a.js

  实战webpack4.0常用配置与优化_html_41

 

 

  实战webpack4.0常用配置与优化_html_42

 

 

  但是此时如果将a和index的关联去掉,如下

  实战webpack4.0常用配置与优化_配置文件_43

  实战webpack4.0常用配置与优化_jquery_44

 

 

  此时两个文件便没有任何关联了... ...

  但此时我们如果想让两个文件关联打包,则如下

  实战webpack4.0常用配置与优化_css_45

 

 

  如下所示

  实战webpack4.0常用配置与优化_jquery_46

 

 

  此时便会将两个文件都打包进去

  实战webpack4.0常用配置与优化_jquery_47

 

 

 

(4)单页与多页html

  a.html引用index.js文件,b.html引用a.js文件

  实战webpack4.0常用配置与优化_html_48

  打包测试如下,只打包了a.js文件... ...

  实战webpack4.0常用配置与优化_配置文件_49

 

 

  修改如下,多入口对应多出口

  实战webpack4.0常用配置与优化_css_50

 

 

  此时再次打包测试如下,此时index.html引入了两个文件

  实战webpack4.0常用配置与优化_热更新_51

 

 

  实战webpack4.0常用配置与优化_html_52

 

 

  但是,我们这里的需求是a.html引用index.js文件,b.html引用a.js文件,所以需要打包多个html文件,所以添加HtmlWebpackPlugin即可

  实战webpack4.0常用配置与优化_jquery_53

  实战webpack4.0常用配置与优化_热更新_54

  打包后如下,且a.html引入两个,b.html引入一个

  实战webpack4.0常用配置与优化_热更新_55

  实战webpack4.0常用配置与优化_html_56

 

(5)热更新

  还原之前所有配置,如下



let path = require('path')
let HtmlWebpackPlugin = require('html-webpack-plugin')/**打包Html插件,自动产生html,并引入打包后的文件 */
let { CleanWebpackPlugin } = require('clean-webpack-plugin')/**手动清除某个文件夹内容,清空指定的目录 */
module.exports = {
/**入口配置 */
entry:'./src/index.js',
/**出口配置 */
output:{
filename:'[name].[hash:5].js',/**自定义打包文件名 */
path:path.resolve(__dirname,'dist')/**node里路径操作需要绝对路径 */
},
/**开发服务器配置 */
devServer:{
contentBase:'./dist',/**启动目录 */
port:3000,/**端口号 */
compress:true,/**服务器压缩 */
open:true,/**自动打开浏览器 */
hot:true,/**热更新 */
},
/**插件 */
plugins:[
/**打包Html插件,自动产生html,并引入打包后的文件 */
new HtmlWebpackPlugin({
filename:'a.html', /* 打包出来的文件名*/
template:path.resolve(__dirname,'./src/index.html'),/**打包的html文件 */
title:'首页',
minify:{/**压缩 */
removeAttributeQuotes:true,/**去除双引号 */
collapseWhitespace:true,/**折叠代码为一行 */
},
hash:true,/**清除缓存用的 */
}),
/**清空匹配的路径 */
new CleanWebpackPlugin()
],
/**模块设置 */
module:{},
/**模式设置 */
mode:'development',
/**配置解析 */
resolve:{}
}


  实战webpack4.0常用配置与优化_热更新_57

 

 

  当我们在编辑代码保存时,浏览器会自动更新... ...

  但是有时我们并不想页面所有数据更新,例如vuex和redux状态会丢失,所以我们可以使用插件局部更新

  1、开启开发服务配置

  实战webpack4.0常用配置与优化_jquery_58

 

 

  2、引入插件,webpack内置的哦

  实战webpack4.0常用配置与优化_配置文件_59

 

 

  实战webpack4.0常用配置与优化_配置文件_60

 

 

  3、分析:此时还是会整个页面刷新,因为并不知道修改了哪个模块,所以需要添加判断(热更新应用通知,实现局部刷新,即结合该方法的回调函数实现该模块的更新

  实战webpack4.0常用配置与优化_热更新_61

 

 

  接下来进行优化,直接调用即可

  实战webpack4.0常用配置与优化_css_62

 

 

  注意位置:在index.js文件进行配置添加

  实战webpack4.0常用配置与优化_热更新_63

 

 

 

  

(6)样式打包

  1、新建src/index.css文件

    实战webpack4.0常用配置与优化_jquery_64

 

 

  2、分析:如果直接引入样式文件进行打包,则无效... ...因为webpack默认只打包js文件

    实战webpack4.0常用配置与优化_html_65

 

 

    所以处理css模块需要利用loader

    实战webpack4.0常用配置与优化_配置文件_66

  3、安装相关依赖



①style-loader将样式代码插入style
②css-loader将css作为模块,插入style标签内部
③less、less-loader
④stylus、stylus-loader
⑤node-sass、sass-loader
...


    这里我们演示下css-loader、style-loader、less、less-loader

    实战webpack4.0常用配置与优化_jquery_67

 

 

    接下来开始配置

  4、配置module模块处理规则,写成对象形式方便传参option(注意解析顺序:自下而上,因为先解析成css模块,再将其放到style内

    实战webpack4.0常用配置与优化_css_68

    接下来新建一个less文件

    实战webpack4.0常用配置与优化_热更新_69

 

 

    实战webpack4.0常用配置与优化_css_70

 

 

    然后引入less  

    实战webpack4.0常用配置与优化_热更新_71

 

 

    结果如下

    实战webpack4.0常用配置与优化_配置文件_72

 

 

    实战webpack4.0常用配置与优化_html_73

 

 

 

(7)样式抽离---css 和 less 抽离到同一个 css 文件 common.css 里

  此时存在问题,style标签太多,我们利用link引入更加优雅一些...

  测试可以得知改变less文件,也可以触发热更新

  实战webpack4.0常用配置与优化_jquery_74

 

  原理如下:CSS-loader具有热更新功能

 

  实战webpack4.0常用配置与优化_配置文件_75

 

 

  如果想实现样式抽离,需要安装下面两个plugin插件

  实战webpack4.0常用配置与优化_jquery_76



extract-text-webpack-plugin在webpack3里就存在,在新版本后面加@next后缀
mini-css-extract-plugin将来可能替代上述插件的插件,目前不太稳定


  1、引入

  实战webpack4.0常用配置与优化_html_77

 

 

  2、使用:注意这里我们要将其改为link形式,所以不再需要style-loader

  实战webpack4.0常用配置与优化_jquery_78

  3、实例化调用插件方法

  实战webpack4.0常用配置与优化_jquery_79

  4、抽离文件名

  实战webpack4.0常用配置与优化_配置文件_80

  5、打包测试如下

  实战webpack4.0常用配置与优化_html_81

 

(8)样式抽离---分开抽离,分别把 css 和 less 放在两个 css 文件中 link 到页面

 

 

 

  实战webpack4.0常用配置与优化_热更新_82

 

 

  实战webpack4.0常用配置与优化_css_83

 

 

  实战webpack4.0常用配置与优化_配置文件_84

 

 

  打包测试结果

  实战webpack4.0常用配置与优化_jquery_85

 

 

 

  

(9)样式抽离--最新方案

  弱点:只能合成一个css文件,不能分开抽离




从上图我们可以看到,我们所写的css、less样式都会放到head标签中,那么我们如何单独把css的内容抽离出来用link标签的形式引入呢:

  • 首先,先安装抽离 ​​css​​ 的插件 : ​​yarn add mini-css-extract-plugin -D​
  • 安装好之后,在 配置文件中 引入:​​let MiniCssExtractPlugin = require('mini-css-extract-plugin')​
  • 然后在配置文件中的插件配置中进行配置:



plugins: [ //数组, 放着所有的 webpack插件
new MiniCssExtractPlugin({
filename:'main.css', //抽离出来的css的文件的名字
})
],


  • 然后选择,到底是 css 文件要抽离,还是 less 文件要抽离,那个要抽离就给那个 加上抽离插件的内置loader。(在模块中的 css 、less 规则中加 ):如下:



module: { //模块
rules: [ //规则
{
test: /\.css$/, //用正则来匹配以 css 结尾的文件
use: [
MiniCssExtractPlugin.loader,//这个loader的作用是:抽离出来 css然后用 link 标签引入到 模板文件中
'css-loader'
]

![](https://user-gold-cdn.xitu.io/2019/11/14/16e68118b17b28e6?w=1477&h=705&f=jpeg&s=127105) },
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,//这个loader的作用是:抽离出来 css然后用 link 标签引入到 模板文件中
'css-loader',
'less-loader' //把 less --->转换为 css
]
}
]
}


  • 运行​​npm run build​​命令,看一下是否单独抽离出来css文件: 实战webpack4.0常用配置与优化_css_86

可以看到,我们的css文件已经被单独抽离出来了,启动一下服务看一下页面效果:

   实战webpack4.0常用配置与优化_配置文件_87

   实战webpack4.0常用配置与优化_css_88

实战webpack4.0常用配置与优化_css_89

现在已经变成抽离出来的css文件是用link标签来引入的。



 (10)样式抽离后的注意事项

  样式抽离后因为放到link标签,所以更改样式时,服务器无法热更新哦。设置如下

  实战webpack4.0常用配置与优化_jquery_90

 

  将disable属性改为true后便无法将其改为link引入,即该设置无效,便可以在开发时候热更新,上线前记得改为false。

  注意2:fallback改为style-loader,即当无法改为link引入时,使用style内敛,以此实现热更新目的

  实战webpack4.0常用配置与优化_html_91

 

(11)多余样式代码的删除

  场景:项目引入bootstrap,但有很多多余没用的而样式,我们可能只用到一两种... ....

  如下所示,这里我们手动添加一些无用的多余样式

  实战webpack4.0常用配置与优化_css_92

 

  我们希望打包时,如果用不到,则不打包这些样式代码,此时需要用到插件purifycss-webpack,它会在打包时调用purify-css插件,且搜索时需要glob插件

  1、安装依赖

  实战webpack4.0常用配置与优化_html_93

 

  2、引入使用(使用注意事项,必须在css-plugin的下面,因为需要先去除,再打包)

  实战webpack4.0常用配置与优化_css_94

  结合文档看先使用规范

  实战webpack4.0常用配置与优化_配置文件_95

  实战webpack4.0常用配置与优化_热更新_96

  结果如下

  实战webpack4.0常用配置与优化_jquery_97

 

  

(12)css代码自动添加前缀

  如下所示,希望在添加时自动加上前缀

  实战webpack4.0常用配置与优化_html_98

  1、安装依赖



npm install postcss-loader autoprefixer -D


  2、添加配置文件src/postcss.config.js

  实战webpack4.0常用配置与优化_jquery_99

  3、使用

  实战webpack4.0常用配置与优化_配置文件_100

 

  4、打包测试

  实战webpack4.0常用配置与优化_配置文件_101

 

 

  实战webpack4.0常用配置与优化_热更新_102

 

 

(13)解析ES6

参考文章:​​javascript:void(0)​




1.​​ES6​​ 或者 更高级的语法 转化为 ​​ES5​​  (babel)

1.安装 babel-loader:转换加载器,和 babel/core(babel 的核心),和​​babel/preset-env​​ (转化模块)

yarn add babel-loader @babel/core @babel/preset-env
复制代码


2.安装完成之后,在配置文件中配置 ​​js​​规则:

 {
test: /\.js$/,
use:{
loader: 'babel-loader',
options: { // 用 babel-loader,需要把 es6 转换为 es5
presets: [ //预设库
'@babel/preset-env' //包含把es6转换为es5的模块
'@babel/preset-react' //解析 react语法
]
}
}
},
复制代码
//配置完成后就可以解析 `es6` 语法。 

//更高一级的语法的配置:(注意:先安装完在配置)

{
test: /\.js$/,
use:{
loader: 'babel-loader',
options: { // 用 babel-loader,需要把 es6 转换为 es5
presets: [ //预设库
'@babel/preset-env' //包含把es6转换为es5的模块
],
plugins: [
//更高级的语法解析(如装饰器写法)
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }]
]
}
}
},
复制代码


2.​​ES6​​ 或者 更高级的语法 转化为 ​​ES5​​ 常用插件:
  1. @babel / plugin-transform-runtime (可以处理异步,如 Promise等)代码运行时的包 开发依赖:
    yarn add @babel / plugin-transform-runtime -D 先进行插件的安装
  2. @babel/runtime : 这个包上线时需要,所以安装时不要加 -D
    yarn add @babel/runtime
  3. 安装好之后,进入到配置文件中配置安装好的插件:
    {
test: /\.js$/,
use:{
loader: 'babel-loader',
options: { // 用 babel-loader,需要把 es6 转换为 es5
presets: [ //预设库
'@babel/preset-env' //包含把es6转换为es5的模块
],
plugins: [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }],
"@babel/plugin-transform-runtime" //加入到这个位置
]
}
},
include:path.resolve(__dirname,'src'), //找 src下面的 js
exclude:/node_modules/ //不包含 node_modules 下面的 js
},
复制代码


默认找到的是全部的 ​​js​​, 我们还得写一些规则来让它只找 ​​src​​ 下面的 ​​js​​文件。

4.还有一些更高级的语法不支持转换,安装一个补丁模块:

​yarn add @babel/polyfill​​ 这个模块在代码运行时需要,所以安装时不要加 -D。

用的时候需要在上面引入这个模块: ​​require('@babel/polyfill')​

3.JS校验:(校验器:eslint)
  1. 需要先安装 eslinteslint-loader
    yarn add eslint eslint-loader -D
  2. 然后在配置文件中的模块配置中去配置 js 规则:
  {
//在配置一个 js 规则,用来校验 js
test: /\.js$/,
use: {
loader: 'eslint-loader',
options: {
enforce: 'pre' // 强制 强制在下一个 loader 之前执行 post 是后面
}
}
},
{
test: /\.js$/,
use:{
loader: 'babel-loader',
options: { // 用 babel-loader,需要把 es6 转换为 es5
presets: [ //预设库
'@babel/preset-env' //包含把es6转换为es5的模块
],
plugins: [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }],
"@babel/plugin-transform-runtime"
]
}
},
include: path.resolve(__dirname, 'src'), // 包含 src 下面的 js 文件
exclude: /node_modules/ // 去除掉 node_modules
},
复制代码


4.全局变量引入问题(第三方模块的使用):

loader 的类型:​​pre​​ 前面执行的 loader, normal 普通 loader,内联 loader,post 后置 loader。

用 ​​jquery​​ 举例说明:

​ >>>>> 内联 loader,就是在 代码中就可以直接使用的 loader。

​ 1. 先安装 ​​jquery​​ , ​​yarn add jquery​

​ 2. 在代码中引入:​​import $ from 'jquery'​

​ 3. 将 $ 符 暴露到全局去:那么这就需要一个暴露 全局的 loader:​​expose-loader​​ ,这个loader是内联的。

import $ from 'expose-loader?$!jquery'
复制代码


​ 这是内联 loader 在代码中的直接用法。 ​​jquery​​ 暴露 出 一个 $ 符 到全局。

  1. 也可以在 配置文件中去配置 内联 loader:
    module: { //模块 rules: [ //规则 { test: require.resolve('jquery'), //只要引用了 jquery 就去匹配 use: 'expose-loader?$' }, ] } 复制代码
  2. 注解的方式: 在每个模块中注入 $ 对象:
  • 这个时候需要 webpack 的插件: 先要引入 webpack
  • let webpack = require('webpack')复制代码
  • 然后在配置文件的 插件配置中 去配置:
  • new webpack.ProvidePlugin({ // 在每个模块中都注入 $ (提供插件) $:'jquery' }) 复制代码
  1. 在模板中直接引入 jquerycdn ,但是这样在打包的时候会将 jquery 一起打包,这个时候 需要在 配置文件中添加一个属性来不打包 jquery
    // 表明这是外部引入的,并不需要打包。externals: { jquery: '$' } 复制代码
5.​​webpack​​ 打包图片:

在 ​​js​​ 中创建图片来引入:

// 1)在 js 中创建图片来引入
let image = new Image()
image.src = './logo.png' //就是一个普通的字符串
document.body.appendChild(image)
复制代码


这样来引入的话,找不到这张图片,因为这样写的话图片只是一个普通的字符串。要用​​es6​​的语法来导入图片.

import logo from './logo.png' //把图片引入,返回的结果是一个新的图片地址
let image = new Image()
console.log(logo)
image.src = logo
document.body.appendChild(image)
复制代码


这样写的话是不支持的,需要引入一个 loader 来实现这种写法:​​file-loader​​ 。

安装完成 loader 之后,我们需要到配置文件中去配置 加载图片的规则:

module: { //模块
rules: [ //规则
{
test: /\.(png|jpg|gif)$/,
use: "file-loader"
},
]
}
复制代码


在 ​​css​​ 中引入图片:

background: url('图片地址') /* 可以直接这样来写,这是默认支持的,因为我们用了 css-loader css-loader会吧这个转化为 require()这种写法*/
复制代码


在 ​​html​​ 中直接引入

<img src="./logo.png" alt="">
复制代码


这样写会报错,因为在我们打包的文件中根本找不到这张图片。这个时候我们需要一个 loader 来支持这种写法。

​yarn add html-withimg-loader -D​​ 这个 loader 会帮我们解析 ​​html​​ 编译图片.

安装完成之后到配置文件中配置我们的 loader:

module: { //模块
rules: [ //规则
{
test: /\.html$/,
use: 'html-withimg-loader'
},
]
}
复制代码


一般我们用于图片的loader 不是用 file-loader, 而是用 url-loader

      {
test: /\.(png|jpg|gif)$/,
use: {
// 做一个限制,当我们的图片 小于多少k的时候 用base64 来转换
// 否则用 file-loader 来产生真实的图片
loader: "url-loader",
options: {
limit: 1
}
}
},
复制代码


6.打包文件分类

图片放到 ​​img​​ 文件夹下面:

在配置文件中的 图片 规则中加上一个输出的路劲:

    {
test: /\.(png|jpg|gif)$/,
use: {
// 做一个限制,当我们的图片 小于多少k的时候 用base64 来转换
// 否则用 file-loader 来产生真实的图片
loader: "url-loader",
options: {
limit: 1,
outputPath: 'img/' //这样打包的图片就会放到 img 文件夹下面
}
}
},
复制代码


这样就会把图片生成到 ​​img​​ 文件夹下面。

​css​​ 文件生成到 ​​css​​ 文件夹下面:

在配置文件中,压缩 ​​css​​ 的插件中加入路径:

new MiniCssExtractPlugin({
filename:'css/main.css', //抽离出来的css的文件的名字
}),
复制代码


如何在 引用 资源的时候加上一个域名,在输出的时候加上一个公共的路径:

 output: {  //出口
filename: 'bundle.js', //打包后的的文件名
path: path.resolve(__dirname, 'build'),
publicPath: 'http://www.fanqiang.com' //加上一个公共的路径
},
复制代码


这样的话引用的资源(​​css​​,​​js​​,​​img​​等)都会加上公共的路径。

​ 如果你只想要给某一个资源前面加上公共的路径,比如 图片上面加上公共路径,那么就不要在出口中写,只需要在 图片规则中定义即可

{
test: /\.(png|jpg|gif)$/,
use: {
// 做一个限制,当我们的图片 小于多少k的时候 用base64 来转换
// 否则用 file-loader 来产生真实的图片
loader: "url-loader",
options: {
limit: 1,
outputPath: '/img/',
publicPath: 'http://www.fanqiang.com' //公共路径
}
}
},


 

 

 

 

 

 

 

.