资讯专栏INFORMATION COLUMN

webpack4初学习

Object / 3263人阅读

webpack基于node,因此想要学习webpack首先要安装node。
webpack4要安装node8.2以上版本。

1、安装webpack

为什么选择本地安装,主要是由于以后介绍热更新这一部分不会报错,如果全局安装热更新就会报错,以本部分为基础依次介绍,保证各部分不会出错。

mkdir webpack-test
cd webpack-test
npm init //初始化npm,都选择默认,文件夹自动创建package.json
npm i webpack webpack-cli -D  // 本地安装webpack

★ npm i -D 是 npm install --save-dev 的简写,是指安装模块并保存到 package.json 的 devDependencies中,主要在开发环境中的依赖包

2、初试0配置打包

webpack4可以支持0配置打包,这里所说的0配置又是什么呢?当然在开发者眼中0配置的东西,那根本是无法用的,因为不够智能,那么我们就来看看做到了哪些0配置。
在使用webpack进行打包的时候,默认情况下会将src下的入口文件(index.js)进行打包。

a. 根目录下创建文件夹src,并创建index.js文件

document.write("Hello webpack!")

b. 打包测试

如果直接打包:


最后提示:
WARNING in configuration //配置警告
大体意思:是mode没有设置,webpack生产环境无法获取mode值,请设置mode来确定开发环境还是生产环境

通过以下手段皆可以不报错:

// node v8.2版本以后都会有一个npx
// npx会执行bin里的文件

npx webpack     // 不设置mode的情况下 打包出来的文件自动压缩
npx webpack --mode development  // 设置mode为开发模式,打包后的文件不被压缩

当执行npx webpack命令的时候,webpack会自动查找项目中src目录下的index.js文件,然后进行打包,生成一个dist目录并存在一个打包好的main.js文件
这些算是0配置的操作了,名字都是定义好的,不能变,想想也很鸡肋

目录结构:

3、配置执行文件

重新创建目录:lesson_test

初始化:npm init //全部选择默认即可

创建webpack.config.js配置文件

webpack.config.js基本配置项:

module.exports = {
    entry: "",               // 入口文件
    output: {},              // 出口文件
    module: {},              // 处理对应模块
    plugins: [],             // 对应的插件
    devServer: {},           // 开发服务器配置
    mode: "development"      // 模式配置
}

a.根目录下创建src文件夹,并在src目录下创建index.js:

document.write("Hello webpack!")

b.配置文件webpack.config.js:

const path = require("path")

module.exports = {
    entry: "./src/index.js",
    output: {
        filename: "bundle.js",
        path: path.resolve(__dirname, "./dist")
    },
    mode: "development"
}

c.执行webpack

通过简单打包,在根目录下多出一个文件夹

查看一下dist文件夹下bundle.js可见以下代码,证明打包成功

友情提示:

在我们每次npm run build的时候都会在dist目录下创建很多打好的包,如果积累过多可能也会混乱,所以应该在每次打包之前将dist目录下的文件都清空,然后再把打好包的文件放进去
这里提供一个clean-webpack-plugin插件

npm i clean-webpack-plugin -D

webpack.config.js中添加以下配置代码:

let CleanWebpackPlugin = require("clean-webpack-plugin");

module.exports = {
    plugins: [
        // 打包前先清空
        new CleanWebpackPlugin("dist")  
    ]
}
4、配置开发环境/生产环境

上边部分我们测试已经发现,直接打包会警告配置环境,本部分着重介绍一下。

环境配置在package.json文件:

{
  "name": "lesson_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "dev": "webpack --mode development", // 开发环境,和上部分npx webpack --mode development对比我们可以发现点端倪
    "build": "webpack --mode production" // 生产环境
  },
  "author": "",
  "license": "ISC"
}

开发环境和生产环境打包会有什么区别呢?
"dev": "webpack --mode development", // 开发环境,打包后文件是未压缩的文件
"build": "webpack --mode production" // 生产环境,打包后文件是压缩过的文件

配置完成后,通过执行命令:

a. 执行 npm run dev

打包后文件为非压缩文件

b. 执行 npm run build

打包后文件为压缩文件

5、多文件入口配置

假如src目录下多个文件入口,又该如何配置webpack.config.js文件呢。

具体方案:

一种是没有关系的但是要打包到一起去的,可以写一个数组,实现多个文件打包

另一种就是每一个文件都多带带打包成一个文件的

下面就来看看这两种方式的写法,配置代码:

const path = require("path")

module.exports = {
    // 1.写成数组的方式就可以打出多入口文件,不过这里打包后的文件都合成了一个
    // entry: ["./src/index.js", "./src/login.js"],
    // 2.真正实现多入口和多出口需要写成对象的方式
    entry: {
        index: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        // 1. filename: "bundle.js",
        // 2. [name]就可以将出口文件名和入口文件名一一对应
        //filename: "[name].js", // 打包后会生成index.js和login.js文件
        filename: "[name].[hash:16].js", //生成文件名含有16位哈希值
        path: path.resolve(__dirname, "dist")
    },
    mode: "development"
}

执行npm run dev结果

目录结构(生成文件的名字带有16位哈希值):

6、打包html配置

webpack的核心功能是打包js的,html、style、css、less、sass、img等等需要引入各种loader,到达这一部分,每一步都需要引入对应的插件。

html需要安装html-webpack-plugin插件,开始引入:

npm i html-webpack-plugin -D  // 本地安装

因为是个插件,所以需要在webpack.config.js里引用一下。

a. 单文件入口配置

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin") // 引入html打包插件

module.exports = {
    entry: "./src/index.js",
    output: {
        filename: "index.js",
        path: path.resolve(__dirname, "dist")
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            hash: true // 在html模板中自动添加?20位哈希值
        })
    ],
    mode: "development"
}

执行npm run dev 生成目录

打开index.html文件,可见js文件后添加了“?20位哈希值”

b. 多文件入口配置

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],  // 对应关系,main.js对应的是index.html,这里特意修改为main,方便理解,以下会和目录文件作对比就一目了然了
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],  // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        })
    ],
    mode: "development"
}

由目录可见,dist文件夹下生成index.html对应main.js、login.html对应login.js

上面基本介绍完了html和js的打包配置了,现在我们还缺一个好兄弟css,webpack对css的解析需要用到loader,所以我们先提前安装好,待会好方便使用

7、引入css文件

这里涉及到两种样式:

html页面内style样式 ,本部分介绍

html引入外部样式表 第8部分介绍

npm i style-loader css-loader -D  // stylecss

// 引入less文件的话,也需要安装对应的loader
npm i less less-loader -D

文件目录结构

a. 配置样式

b. 在js文件中引入样式

c. 配置webpack.config.js文件

说明:配置module添加规则,本部分添加可css、less的匹配打包规则

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: ["style-loader", "css-loader"]
            },
            {
                test: /.less$/,
                use: ["style-loader", "css-loader", "less-loader"]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],  // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],  // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        })
    ],
    mode: "development"
}

d. 执行npm run dev打包

生成静态文件index.html

生成静态文件login.html

此时打包后的css文件是以行内样式style的标签写进打包后的html页面中,如果样式很多的话,我们更希望直接用link的方式引入进去,这时候需要把css拆分出来

extract-text-webpack-plugin插件相信用过的人都知道它是干什么的,它的功效就在于会将打包到js里的css文件进行一个拆分

8、拆分css文件

本部分也就是将css文件拆分出来,html页面以的方式引入。

// @next表示可以支持webpack4版本的插件
npm i extract-text-webpack-plugin@next -D

配置webpack.config.js

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin") // 引入插件

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: ExtractTextWebpackPlugin.extract({
                    // 将css用link的方式引入就不再需要style-loader了
                    use: "css-loader"
                })
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],
            hash: true
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],
            hash: true
        }),
        new ExtractTextWebpackPlugin("css/style.css") // 拆分后会把css文件放到dist目录下的css/style.css
    ],
    mode: "development"
}

配置中只对index.html文件引入样式,而login.html没有引入,因此要注释掉login.js引入的样式

// import "./less/style.less" // 注释掉这句代码

document.write("

Welcome to webpack!

")

执行npm run dev,生成dist目录

首页静态页面代码,可见以link的方式引入了css样式

9、拆分多个css文件

配置webpack.config.js文件

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: "css-loader"
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"], // 一定要注意这里
                    fallback: "style-loader" // 缺少这里也是无法编译less
                })
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],  // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],  // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        styleCss,
        styleLess
    ],
    mode: "development"
}

index.js文件

import "./css/style.css"
import "./less/style.less" // 引入style.less

document.write("

Hello webpack!

测试less样式是否引入

")

执行 npm run dev ,获取静态页面截图,可见全部正常引入

执行效果

生成文件目录:

10、样式表引用图片

处理图片方面,也需要loader

npm i file-loader url-loader -D

这里着重介绍一下file-loader和url-loader:

本部分介绍url-loader(增强的file-loader);

url-loader作用:根据需求选择性的把某些小图片编码成base64格式写进页面;从而减少服务器请求。优化性能。

url-loader解决的问题:
如果图片较多,会发很多http请求,会降低页面性能。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

url-loader和file-loader是什么关系呢?
简答地说,url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。

通过上面的介绍,我们可以看到,url-loader工作分两种情况:
1.文件大小小于limit参数,url-loader将会把文件转为DataURL;
2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。因此我们只需要安装url-loader即可。

如果是在css文件里引入的如背景图之类的图片,就需要指定一下相对路径
webpack.config.js配置:

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: "css-loader",
                    publicPath: "../" // 样式根据相对路径引用到图片资源
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192, // 小于8k的图片自动转成base64格式,并且不会存在实体图片
                            outputPath: "images" // 图片输出路径
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],
            hash: true
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],
            hash: true
        }),
        styleCss,
        styleLess
    ],
    mode: "development"
}

样式style.css代码:

/* style.css */
@charset "utf-8";

.logo {
    display: block;
    width: 222px;
    height: 222px;
    background: url(../images/logo.png) no-repeat; // 这里的logo.png大小大于8K,以下生成在dist文件夹下images目录
}
.color-red {
    color: #f00;
}

在css中指定了publicPath路径这样就可以根据相对路径引用到图片资源了,如下图所示

执行npm run dev 生成目录结构:

11、js文件引入图片

url-loader能自动识别CSS代码中的图片路径并将其打包至指定目录,但是JS就不同了,我们来看下面的例子。

// index.js
var img = new Image();
img.src = "./images/logo.png";
document.body.appendChild(img);

如果不使用Webpack打包,正常情况下只要路径正确图片是能够正常显示的。然而,当使用Webpack打包后,我们会发现图片并未被成功打包到dist目录,自然图片也无法显示出来。
这其实是因为Webpack并不知道"../images/logo.png"是一张图片,如果要正常打包的话需要先将图片资源加载进来,然后再将其作为图片路径添加至图片对象。具体代码如下:

// index.js
import imgUrl from "./images/logo.png" // 引入图片(路径),如果小于8K格式为base64,大于8K为设置路径dist目录下"./images/logo.png"

const img = new Image() // 实例一个图片对象
img.src = imgUrl;
document.body.appendChild(img); // 添加到dom节点中

完整index.js文件:

import "./css/style.css"
import "./less/style.less"
import imgUrl from "./images/logo.png" // 引入图片

const img = new Image()
img.src = imgUrl
document.body.appendChild(img)
// document.write(imgUrl) // "./images/logo.png"

document.write("

Hello webpack!

测试第二个css样式是否引入

")

完整webpack.config.js配置文件(相比第10部分无任何变化):

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: "css-loader",
                    publicPath: "../" // 样式根据相对路径引用到图片资源
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            outputPath: "images", // 图片输出路径
                            name: "[name].[ext]"
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"], // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"], // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        styleCss,
        styleLess
    ],
    mode: "development"
}

执行npm run dev生成文件目录

生成静态文件


可见图片在js中正常加载到页面中,由于logo.png大于8K,被打包到dist文件目录的images文件中。如果图片小于8K,则以base64编码格式写入页面进项渲染。

12、html页面引入图片

页面中经常会用到img标签,img引用的图片地址也需要一个loader来进行处理

npm i html-withimg-loader -D

完整wabpack.config.js配置:

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: "css-loader",
                    publicPath: "../" // 样式根据相对路径引用到图片资源
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            outputPath: "images", // 图片输出路径
                            name: "[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /.(htm|html)$/,
                use: "html-withimg-loader" // 引入html-withimg-loader
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"], // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"], // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        styleCss,
        styleLess
    ],
    mode: "development"
}

打包后生成对应目录:

13、引入字体图片和SVG图片

字体图标和svg图片都可以通过file-loader来解析,在第11部分已经进行安装。
webpack.config.js引入loader

module.exports = {
    module: {
        rules: [
            {
                test: /.(eot|ttf|woff|svg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            outputPath: "iconfont" // 打包到指定文件夹
                        }
                    }
                ]
            }
        ]
    }
}

这样即使样式中引入了这类格式的图标或者图片都没有问题了,img如果也引用svg格式的话,配合上面写好的html-withimg-loader就都没有问题了。

在index.js引入样式:

import "./css/style.css"
import "./less/style.less"
import "./iconfont/iconfont.css" // 引入字体图片
import imgUrl from "./images/pic.jpg" // 引入图片链接

const img = new Image()
img.src = imgUrl
document.body.appendChild(img)
// document.write(imgUrl) // "./images/logo.png"

document.write("

Hello webpack!

测试第二个css样式是否引入


")

完整的webpack.config.js配置:

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: "css-loader",
                    publicPath: "../" // 样式根据相对路径引用到图片资源
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            outputPath: "images", // 图片输出路径
                            name: "[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /.(eot|ttf|woff|svg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            outputPath: "iconfont" // 打包到指定文件夹
                        }
                    }
                ]
            },
            {
                test: /.(htm|html)$/,
                use: "html-withimg-loader" // 引入html-withimg-loader,将图片转化为base64图片
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],
            hash: true
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],
            hash: true
        }),
        styleCss,
        styleLess
    ],
    mode: "development"
}

打包后目录文件:

对应静态文件

14、添加CSS3前缀

通过postcss中的autoprefixer可以实现将CSS3中的一些需要兼容写法的属性添加响应的前缀,这样省去我们不少的时间

npm i postcss-loader autoprefixer -D // 安装postcss-loader 和 autoprefixer

安装后,我们还需要像webpack一样写一个config的配置文件,在项目根目录下创建一个postcss.config.js文件,配置如下:

const Autoprefixer = require("autoprefixer")

module.exports = {
    plugins : [
        Autoprefixer
    ]
}

然后在webpack里配置postcss-loader,webapack.config.js完整代码:

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: ["css-loader", "postcss-loader"], // 配置postcss-loader
                    fallback: "style-loader",
                    publicPath: "../"
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            outputPath: "images",
                            name: "[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /.(eot|ttf|woff|svg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            outputPath: "iconfont"
                        }
                    }
                ]
            },
            {
                test: /.(htm|html)$/,
                use: "html-withimg-loader"
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"],
            hash: true
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"],
            hash: true
        }),
        styleCss,
        styleLess
    ],
    mode: "development"
}

index.js添加测试元素

样式表style.css,简单书写了animation动画效果,没有添加兼容浏览器的前缀

/* style.css */
@charset "utf-8";

.logo {
    display: block;
    width: 222px;
    height: 222px;
    background: url(../images/logo.png) no-repeat;
}
.color-red {
    color: #f00;
}
.test-css3 {
    position: absolute;
    left: 500px;
    top: 0;
    width: 100px;
    height: 100px;
    background-color: #f00;
    animation: myfirst 5s linear 2s infinite alternate running;
}
@keyframes myfirst {
    0% {
        background: #f00;
        left: 500px;
        top: 0;
    }
    25% {
        background: #ff0;
        left: 900px;
        top: 0;
    }
    50% {
        background: #f0f;
        left: 900px;
        top: 400px;
    }
    75% {
        background: #000;
        left: 500px;
        top: 400px;
    }
    100% {
        background: #0f0;
        left: 500px;
        top: 0;
    }
}

执行npm run dev 后生成的style.css代码自动添加了-webkit-前缀

15、转义ES6

在实际开发中,我们在大量的使用着ES6及之后的api去写代码,这样会提高我们写代码的速度,不过由于低版本浏览器的存在,不得不需要转换成兼容的代码,于是就有了常用的Babel。
bable可以将ES6代码转义ES5代码,安装如下:

npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 -D

babel兼容ES6和草案api,通过一个.babelrc文件来配置一下,对这些版本的支持

// .babelrc
{
    "presets": ["env", "stage-0"]   // 从右向左解析
}

我们再在webpack里配置一下babel-loader既可以做到代码转成ES5了

module.exports = {
    module: {
        rules: [
            {
                test:/.js$/,
                use: "babel-loader",
                include: /src/,          // 只转化src目录下的js
                exclude: /node_modules/  // 排除掉node_modules,优化打包速度
            }
        ]
    }
}

添加本部分配置,完整wabpack.config.js代码:

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")
const CleanWebpackPlugin = require("clean-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: ["css-loader", "postcss-loader"],
                    fallback: "style-loader",
                    publicPath: "../" // 样式根据相对路径引用到图片资源
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.js$/,
                use: "babel-loader",
                include: "/src/",
                exclude: "/node_modules/"
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            outputPath: "images", // 图片输出路径
                            name: "[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /.(eot|ttf|woff|svg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            outputPath: "iconfont" // 打包到指定文件夹
                        }
                    }
                ]
            },
            {
                test: /.(htm|html)$/,
                use: "html-withimg-loader" // 引入html-withimg-loader,将图片转化为base64图片
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            chunks: ["main"], // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            chunks: ["login"], // 对应关系,index.js对应的是index.html
            hash: true // 在html模板中自动添加?20位哈希值
        }),
        styleCss,
        styleLess,
        new CleanWebpackPlugin("dist")
    ],
    mode: "development"
}
16、启动静态服务器和热更新

A.启动静态服务

启动一个静态服务器,默认会自动刷新,就是说你对html,css,js文件做了修改并保存后,浏览器会默认刷新一次展现修改后的效果

module.exports = {
    devServer: {
        contentBase: "./dist",
        host: "localhost",      // 默认是localhost
        port: 8080,             // 端口
        open: true,             // 自动打开浏览器
        // hot: true               // 开启热更新
    }
}

此时我们要对pakage.json文件进行修改:

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build": "webpack --mode production", 
    "dev": "webpack-dev-server --mode development --open" // 使用webpack-dev-server
  }

执行npm run dev 会自动打开默认浏览器,打开http://localhost:8080页面,html,css,js修改保存后页面会自动实时更新。
之前各部分我们每次执行npm run dev都会在根目录生成静态文件目录dist,启动静态服务器,生成dist会储存到内存当中,根目录下不再生成dist文件夹。

B.热更新
在配置devServer的时候,如果hot为true,就代表开启了热更新

module.exports = {
    devServer: {
        contentBase: "./dist",
        host: "localhost",      // 默认是localhost
        port: 8080,             // 端口
        open: true,             // 自动打开浏览器
        hot: true               // 开启热更新
    }
}

但是热更新是指定某个js文件的更新,只需在指定的js文件添加以下代码,表示本文件实现热更新,修改文件后手动刷新页面,会看到修改后的内容;如果不添加以下代码,js文件还是自动刷新

if (module.hot) {
    // 实现热更新
    module.hot.accept();
}

热更新和自动刷新的区别:

js文件被检测到module.hot,就实现热更新,检测不到就是自动刷新;

热更新需要手动刷新获取修改后效果,自动刷新是修改保存,页面自动更新。

完整webpack.config.js代码:

const path = require("path")
const webpack = require("webpack")  // 引入webpack
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")
const CleanWebpackPlugin = require("clean-webpack-plugin")

// 样式处理
const styleCss = new ExtractTextWebpackPlugin("./css/style.css")
const styleLess = new ExtractTextWebpackPlugin("./css/style2.css")

module.exports = {
    entry: {
        main: "./src/index.js",
        login: "./src/login.js"
    },
    output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
    },
    module: {
        rules: [
            {
                test: /.css$/,
                use: styleCss.extract({
                    use: ["css-loader", "postcss-loader"],
                    fallback: "style-loader",
                    publicPath: "../"
                })
            },
            {
                test: /.less$/,
                use: styleLess.extract({
                    use: ["css-loader", "less-loader"],
                    fallback: "style-loader"
                })
            },
            {
                test: /.js$/,
                use: "babel-loader",
                include: "/src/",
                exclude: "/node_modules/"
            },
            {
                test: /.(jpe?g|png|gif)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            limit: 8192,
                            outputPath: "images",
                            name: "[name].[ext]"
                        }
                    }
                ]
            },
            {
                test: /.(eot|ttf|woff|svg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            outputPath: "iconfont"
                        }
                    }
                ]
            },
            {
                test: /.(htm|html)$/,
                use: "html-withimg-loader"
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index.html",
            filename: "index.html",
            title: "首页测试",
            chunks: ["main"],
            hash: true
        }),
        new HtmlWebpackPlugin({
            template: "./src/login.html",
            filename: "login.html",
            title: "登录页测试",
            chunks: ["login"],
            hash: true
        }),
        styleCss,
        styleLess,
        new CleanWebpackPlugin("dist"),
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        contentBase: path.join(__dirname, "dist"),
        host: "localhost",
        port: 8080,
        open: true,
        hot: true // 实现页面热更新
    },
    resolve: {
        extensions: [".js", ".json", ".css"]
    },
    mode: "development"
}

index.js文件代码:

import "./css/style.css"
import "./less/style.less"
import "./iconfont/iconfont.css"
import imgUrl from "./images/pic.jpg" // 引入图片

const img = new Image()
img.src = imgUrl
document.body.appendChild(img)
// document.write(imgUrl) // "./images/logo.png"

document.write("

Hello webpack!

测试第二个css样式是否引入


") if (module.hot) { module.hot.accept() }
17、resolve解析

在webpack的配置中,resolve我们常用来配置别名和省略后缀名

module.exports = {
    resolve: {
        // 别名
        alias: {
            $: "./src/jquery.js"
        },
        // 省略后缀
        extensions: [".js", ".json", ".css"]
    },
}

未完待续

参考链接:
1、https://juejin.im/post/5adea0...
2、https://www.cnblogs.com/cisum...
3、https://www.cnblogs.com/golov...
4、https://www.webpackjs.com/loa...
5、https://www.cnblogs.com/golov...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101245.html

相关文章

  • webpack4.0体验、各版本及parcel性能对比

    摘要:前段时间又发布了新版本我接触的时候已经版本了支持的版本必须打包速度大小比较以及粗浅的试了一下下图所示,黄色为版本绿色为我写的配置,跟基本相似,具体不同下面会介绍蓝色是自带的模式红色为具体大小速度大家可以比较一下,还是很给力的关于配置方面,应 前段时间webpack又发布了新版本webpack4我接触的时候已经4.1版本了node支持的版本必须node: >=6.11.5 webpack...

    MarvinZhang 评论0 收藏0
  • 一个现代化的webpack工程

    摘要:一前言文章介绍了一个现代化的项目的环境是什么样的。其中一个就是引用路径的问题。扩展将单独打包详细介绍见这是一个插件,可以简化创建文件以便为包提供服务。两种环境的配置在中都支持的配置具体的默认配置查询可以移步这里的默认设置。 一 前言 文章介绍了一个现代化的项目的webpack4环境是什么样的。这里只是介绍了基础的功能,如果需要详细的相关只是可以去webpack官网去查阅。代码地址:gi...

    MyFaith 评论0 收藏0
  • vue-cli3.0体验~

    摘要:比如传递给时,使用。为所有的及其预处理文件开启。在生产环境下为和使用在多核机器下会默认开启。是否使用分割供应的包也可以是一个在包中引入的依赖的显性的数组。查阅配置行为。 之前因为parcel的出现,webpack也跟进了零配置vue-cli自然也不能落下,cli3.0也升级到webpack4,并增加许多新特性 安装并创建一个项目 支持npm和yarn npm install -g @v...

    AlphaWallet 评论0 收藏0
  • webpack4+vue2+axios+vue-router的多页+单页混合应用框架

    摘要:适用于主要入口页面生成多页,子页面和次要页面使用单页形式的项目。文件用来存放固定的数据,而文件可更加自由的处理并返回数据。 VUE2的单页应用框架有人分享了,多页应用框架也有人分享了,这里分享一个单页+多页的混合应用框架吧,node.js写了一个简单的mock服务也集成在里面,整体初现雏形,还有很多需要优化和改善的地方。。。 项目结构 │ ├─build ...

    whatsns 评论0 收藏0
  • 前端方便面

    摘要:技术前端布局推进剂间距规范化利用变量实现令人震惊的悬浮效果很棒,但有些情况不适用布局说可能是最全的图片版学习网格布局使用的九大误区图解布局布局揭秘和中新增功能探索版本迭代论基础谈展望对比探究绘图中撤销功能的实现方式即将更改的生命周期几道高 技术 CSS 前端布局推进剂 - 间距规范化 利用CSS变量实现令人震惊的悬浮效果 Flexbox 很棒,但有些情况不适用 CSS布局说——可能是最...

    liaoyg8023 评论0 收藏0

发表评论

0条评论

Object

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<