webpack4.x最详细使用讲解一

摘要:
使用此配置文件,我们只需在终端中运行webpack命令即可打包。此命令将自动引用webpack.config.js文件中的配置

前言

本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,所以本文也比较长,但如果你能动手跟着本文中的例子完整写一次,相信你会觉得Webpack也不过如此。

一、什么是webpack,为什么使用它?

webpack4.x最详细使用讲解一第1张webpack4.x最详细使用讲解一第2张

1.1 什么是webpack?

简单来说,它其实就是一个模块打包器。

1.2 为什么使用它?

如果像以前开发时一个html文件可能会引用十几个js文件,而且顺序还不能乱,因为它们存在依赖关系,同时对于ES6+等新的语法,less, sass等CSS预处理都不能很好的解决……,此时就需要一个处理这些问题的工具。

Webpack就是为处理这些问题而生的,它就是把你的项目当成一个整体,通过一个入口主文件(如:index.js),从这个文件开始找到你的项目所有的依赖文件并处理它们,最后打包成一个(或多个)浏览器可识别的JavaScript文件。

二、一个简单的打包例子

2.1 准备工作

首先新建一个空文件夹,用于创建项目,在终端中进入文件夹,如下我在桌面建了一个名为webpack-project的文件夹,使用终端进入文件夹后,使用npm init命令创建一个package.json文件。

npm init
webpack4.x最详细使用讲解一第2张

webpack4.x最详细使用讲解一第4张webpack4.x最详细使用讲解一第2张

输入这个命令后,终端会问你一系列诸如项目名称,项目描述,作者等信息,不过如果你不打算发布这个模块,直接一路回车就好。(也可以使用npm init -y这个命令来一次生成package.json文件,这样终端不会询问你问题)。 

2.2 安装webpack

如果你想一步到位的话,就把全局webpack和本地项目webpack全都先装了,因为后面一些模块会用到。安装本地项目webapck时把webpack-cli也装上,因为webpack模块把一些功能分到了webpack-cli模块,安装方法如下:

npm install webpack --global                //这是安装全局webpack命令
npm install webpack webpack-cli --save-dev  //这是安装本地项目模块
webpack4.x最详细使用讲解一第2张

tips:

上述命令可采用简写,install可简写为i,--global可简写为-g,--save-dev可简写为-D(这个命令是用于把配置添加到package.json的开发环境配置列表中,后面会提到),--save可简写为-S,同时国内我们可以采用cnpm,配置方法可去这里查看,这样安装速度会相对较快。如下:

cnpm i webpack -g               //这是安装全局webpack命令
cnpm i webpack webpack-cli -D   //这是安装本地项目模块
webpack4.x最详细使用讲解一第2张

 2.3 新建文件

webpack-project文件夹中新建两个文件夹,分别为src文件夹和dist文件夹,接下来再创建三个文件:

  • index.html --放在dist文件夹中;
  • hello.js --放在src文件夹中;
  • index.js --放在src文件夹中;

此时,项目结构如下:

webpack4.x最详细使用讲解一第8张webpack4.x最详细使用讲解一第2张

我们在index.html中写下html代码,它的作用是为了引入我们打包后的js文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Webpack Project</title>
</head>
<body>
    <div id='root'></div>
    <script src="bundle.js"></script>   <!--这是打包之后的js文件,我们暂时命名为bundle.js-->
</body>
</html>
webpack4.x最详细使用讲解一第2张

我们在hello.js中导出一个模块:

// hello.js
module.exports = function() {
    let hello = document.createElement('div');
    hello.innerHTML = "Long time no see!";
    return hello;
  };
webpack4.x最详细使用讲解一第2张

然后在index.js中引入这个模块(hello.js):

//index.js 
const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());
webpack4.x最详细使用讲解一第2张

上述操作就相当于我们把hello.js模块合并到了index.js模块,之后我们打包时就只需把index.js模块打包成bundle.js,然后供index.html引用即可,这就是最简单的webpack打包原理。

2.4 开始进行webpack打包

在终端中使用如下命令进行打包:

// webpack全局安装的情况下
webpack src/index.js --output dist/bundle.js  
// --output可简写为-o
webpack4.x最详细使用讲解一第2张

上述就相当于把src文件夹下的index.js文件打包到dist文件下的bundle.js,这时就生成了bundle.jsindex.html文件引用。

结果如下:

webpack4.x最详细使用讲解一第14张webpack4.x最详细使用讲解一第2张

可以看出webpack同时编译了index.js和hello.js,现在打开index.html,可以看到如下结果: 

webpack4.x最详细使用讲解一第16张webpack4.x最详细使用讲解一第2张

没错,我们已经成功使用webpack进行打包,原来webpack也不过如此嘛!但是,每次都在终端中输入这么长的命令,感觉好烦啊,还好有懒人方法,让我们看看。

2.5 通过配置文件来使用webpack

其实webpack是有很多功能的,也是很方便的,我们可以在当前项目的根目录下新建一个配置文件webpack.config.js,我们写下如下简单配置代码,目前只涉及入口配置(相当于我们的index.js,从它开始打包)和出口配置(相当于我们打包生成的bundle.js)。

// webpack.config.js
module.exports = {
    entry: __dirname + "/src/index.js", // 入口文件
    output: {
        path: __dirname + "/dist", //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    }
}
webpack4.x最详细使用讲解一第2张

注:__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录,即C:UserssjtDeskTopwebpack-project(这是我当前的目录)

但平时我们看到的脚手架配置也比较喜欢采用node.js的path模块来处理绝对路径,所以我们也可以采用如下的写法,和上述的效果是一样的:

// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // 入口文件
    output: {
        path: path.join( __dirname, "/dist"), //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    }
}
webpack4.x最详细使用讲解一第2张

 注:path.join的功能是拼接路径片段。

有了这个配置文件,我们只需在终端中运行webpack命令就可进行打包,这条命令会自动引用webpack.config.js文件中的配置选项,示例如下:

webpack4.x最详细使用讲解一第20张webpack4.x最详细使用讲解一第2张

搞定,是不是这样更方便了,感觉没那么low了,但还能不能更便捷智能呢?那必须的!

2.6 更智能的打包方式

我们现在只在终端中使用webpack命令来进行打包,要是以后在打包的同时还有更多的操作呢,那不是还得写上更多的命令?所以我们得想办法把这些命令都集成起来,这时候之前的package.json文件就派上用场了。
现在的package.json文件大概就是如下这样:

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1" //我们要修改的是这里,JSON文件不支持注释,引用时请清除
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.23.1",
    "webpack-cli": "^3.1.2"
  }
}
webpack4.x最详细使用讲解一第2张

修改如下:

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack", //改成这样,注意使用时把注释删掉
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.23.1",
    "webpack-cli": "^3.1.2"
  }
}
webpack4.x最详细使用讲解一第2张

注:package.json中的script会按你设置的命令名称来执行对应的命令。

这样我们就可以在终端中直接执行npm start命令来进行打包,start命令比较特殊,可以直接npm加上start就可以执行,如果我们想起其他的名称,如build时,就需要使用npm run加上build,即npm run build命令。
现在我们执行npm start命令: 

webpack4.x最详细使用讲解一第24张webpack4.x最详细使用讲解一第2张

OK,搞定,是不是很简单,但webpack的功能远不止于此,下面我们继续。

三、构建本地服务器

现在我们是通过打开本地文件来查看页面的,看起来总感觉比较low,看别人用vue,react框架时都是运行在本地服务器上的,那我们能不能也那样呢?那必须的!
 
3.1 webpack-dev-server配置本地服务器

Webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js构建,它是一个单独的组件,在webpack中进行配置之前需要单独安装它作为项目依赖:

cnpm i webpack-dev-server -D
webpack4.x最详细使用讲解一第2张

devServer作为webpack配置选项中的一项,以下是它的一些配置选项:

  • contentBase :设置服务器所读取文件的目录,当前我们设置为"./dist"
  • port :设置端口号,如果省略,默认为8080
  • inline :设置为true,当源文件改变时会自动刷新页面
  • historyApiFallback :设置为true,所有的跳转将指向index.html

现在我们把这些配置加到webpack.config.js文件上,如下:

// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // 入口文件
    output: {
        path: path.join( __dirname, "/dist"), //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    },
    devServer: {
        contentBase: "./dist", 
// 本地服务器在根目录下生成的index.html文件的模板来源,不指定就不会生成。
// webpack-dev-server实时打包好的main.js(默认名)是托管在内存中,所以在项目根目录中看不到,但是
// 我们可以认为在项目根目录中有一个看不见的main.js。因为上面定义的打包后的文件名叫bundle.js,所以
// 这里打包后的文件名也叫bundle.js。通过package.json中配置的npm run dev命令将打包成bundle.js文件
// (存在根目录下)并默认加载index.html文件
        port: "8088",   // 设置端口号为8088
        inline: true, // 文件修改后实时刷新
        historyApiFallback: true, //不跳转
    }
}
webpack4.x最详细使用讲解一第2张

我们继续在package.json文件中添加启动命令:

{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --open"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.23.1",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.10"
  }
}
webpack4.x最详细使用讲解一第2张

我们把start命令名称改为了build,这样比较语义化,平时的脚手架也多数采用这个名称,我们用dev(development的缩写,意指开发环境)来启动本地服务器,webpack-dev-server就是启动服务器的命令,--open是用于启动完服务器后自动打开浏览器,这时候我们自定义命令方式的便捷性就体现出来了,可以多个命令集成在一起运行,即我们定义了一个dev命令名称就可以同时运行了webpack-dev-server--open两个命令。

现在在终端输入npm run dev运行服务器:

webpack4.x最详细使用讲解一第29张webpack4.x最详细使用讲解一第2张

这样我们即可在http://localhost:8088/中查看页面(退出服务器,可使用ctrl+c后,再按y确认,即可退出服务器运行) 

四、Loaders

loaders是webpack最强大的功能之一,通过不同的loader,webpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,例如把scss转为css,将ES66、ES7等语法转化为当前浏览器能识别的语法,将JSX转化为js等多项功能。

Loaders需要单独安装并且需要在webpack.config.js中的modules配置项下进行配置,Loaders的配置包括以下几方面:

  • test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
  • loader:loader的名称(必须)
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • options:为loaders提供额外的设置选项(可选)

4.1 配置css-loader

如果我们要加载一个css文件,需要安装配置style-loadercss-loader:

cnpm i style-loader css-loader -D
webpack4.x最详细使用讲解一第2张
// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // 入口文件
    output: {
        path: path.join( __dirname, "/dist"), //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    },
    devServer: {
        contentBase: "./dist", // 本地服务器所加载文件的目录
        port: "8088",  // 设置端口号为8088
        inline: true, // 文件修改后实时刷新
        historyApiFallback: true, //不跳转
    },
    devtool: 'source-map',  // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
    module: {
        rules: [
            {
                test: /.css$/,   // 正则匹配以.css结尾的文件
                use: ['style-loader', 'css-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            }
        ]
    }
}
webpack4.x最详细使用讲解一第2张

我们在src文件夹下新建css文件夹,该文件夹内新建style.css文件: 

/* style.css */
body {
    background: gray;
}
webpack4.x最详细使用讲解一第2张

index.js中引用它:

//index.js 
import './css/style.css';  //导入css

const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());
webpack4.x最详细使用讲解一第2张

这时我们运行npm run dev,会发现页面背景变成了灰色。

如果是要编译sass文件呢?

4.2 配置sass

cnpm i sass-loader node-sass -D // 因为sass-loader依赖于node-sass,所以还要安装node-sass
webpack4.x最详细使用讲解一第2张

增加sass的rules:

// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // 入口文件
    output: {
        path: path.join( __dirname, "/dist"), //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    },
    devServer: {
        contentBase: "./dist", // 本地服务器所加载文件的目录
        port: "8088",  // 设置端口号为8088
        inline: true, // 文件修改后实时刷新
        historyApiFallback: true, //不跳转
    },
    devtool: 'source-map',  // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
    module: {
        rules: [
            {
                test: /.css$/,   // 正则匹配以.css结尾的文件
                use: ['style-loader', 'css-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            },
            {
                test: /.(scss|sass)$/,   // 正则匹配以.scss和.sass结尾的文件
                use: ['style-loader', 'css-loader', 'sass-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            }
        ]
    }
}
webpack4.x最详细使用讲解一第2张

在css文件夹中新建blue.scss文件:

/* blue.scss */
$blue: blue;
body{
    color: $blue;
} 
webpack4.x最详细使用讲解一第2张

index.js中引入blue.scss

//index.js 
import './css/style.css';   // 导入css
import './css/blue.scss';   // 导入scss

const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());
webpack4.x最详细使用讲解一第2张

这时npm run dev重新启动服务器,应该会出现如下结果:

webpack4.x最详细使用讲解一第39张webpack4.x最详细使用讲解一第2张

还有诸如图片loader、字体loader等就不一一列出来了,感兴趣的可前往webpack官网查看,都是一样的套路。

五、Babel

Babel其实是一个编译JavaScript的平台,它可以编译代码帮你达到以下目的:

  • 让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持;
  • 让你能使用基于JavaScript进行了拓展的语言,比如React的JSX;

5.1 Babel的安装与配置

Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析ES6的babel-preset-env包和解析JSX的babel-preset-react包)。

cnpm i babel-core babel-loader babel-preset-env babel-preset-react -D
// babel-preset-env的env表示是对当前环境的预处理,而不是像以前使用babel-preset-es2015只能针对某个环境
webpack4.x最详细使用讲解一第2张
// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // 入口文件
    output: {
        path: path.join( __dirname, "/dist"), //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    },
    devServer: {
        contentBase: "./dist", // 本地服务器所加载文件的目录
        port: "8088",  // 设置端口号为8088
        inline: true, // 文件修改后实时刷新
        historyApiFallback: true, //不跳转
    },
    devtool: 'source-map',  // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
    module: {
        rules: [
            {
                test: /.css$/,   // 正则匹配以.css结尾的文件
                use: ['style-loader', 'css-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            },
            {
                test: /.(scss|sass)$/,   // 正则匹配以.scss和.sass结尾的文件
                use: ['style-loader', 'css-loader', 'sass-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            },
            {                             // jsx配置
                test: /(.jsx|.js)$/,   
                use: {                    // 注意use选择如果有多项配置,可写成这种对象形式
                    loader: "babel-loader",
                    options: {
                        presets: [
                            "env", "react"
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
}
webpack4.x最详细使用讲解一第2张

现在我们已经可以支持ES6及JSX的语法了,我们用react来试试,但使用react还得先安装两个模块reactreact-dom

cnpm i react react-dom -D
webpack4.x最详细使用讲解一第2张

接下来我们把hello.js文件修改一下:

// hello.js
import React, {Component} from 'react'; // 这两个模块必须引入

let name = 'Alan';

export default class Hello extends Component{
    render() {
        return (
            <div>
                {name}
            </div>
        );
    }
}
webpack4.x最详细使用讲解一第2张

修改index.js文件:

//index.js 
import './css/style.css';  // 导入css
import './css/blue.scss';  // 导入scss

import React from 'react';
import {render} from 'react-dom';
import Hello from './hello'; // 可省略.js后缀名

render(<Hello />, document.getElementById('root'));
webpack4.x最详细使用讲解一第2张

此时运行npm run dev后你可能会发现如下结果:

webpack4.x最详细使用讲解一第46张webpack4.x最详细使用讲解一第2张

这是因为官方默认babel-loader | babel对应的版本需要一致: 即babel-loader需要搭配最新版本babel,详细可参考这篇博客。

两种解决方案:

  • 回退低版本
cnpm i babel-loader@7 babel-core babel-preset-env -D
webpack4.x最详细使用讲解一第2张
  • 更新到最高版本:
cnpm i babel-loader @babel/core @babel/preset-env webpack -D
webpack4.x最详细使用讲解一第2张

我这里采取的是第一个方案,回退后,再此运行npm run dev,得到如下结果:

webpack4.x最详细使用讲解一第50张webpack4.x最详细使用讲解一第2张

到这里了是不是感觉很爽,不就是配置嘛,想要使用什么就配置什么。

5.2 优化babel配置

虽然babel完全可以在webpack.config.js中进行配置,但现在不是都提倡模块化嘛,也许之后babel膨胀了,增加了更多的配置项呢?

那我们不如把它提取出来,把它放到根目录下的.babelrc文件下(webpack会自动调用.babelrc里的babel配置选项)。

我们在项目根目录下新建.babelrc文件:

webpack4.x最详细使用讲解一第52张webpack4.x最详细使用讲解一第2张

// webpack.config.js
const path = require('path');
module.exports = {
    entry: path.join(__dirname, "/src/index.js"), // 入口文件
    output: {
        path: path.join( __dirname, "/dist"), //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件的文件名
    },
    devServer: {
        contentBase: "./dist", // 本地服务器所加载文件的目录
        port: "8088",  // 设置端口号为8088
        inline: true, // 文件修改后实时刷新
        historyApiFallback: true, //不跳转
    },
    devtool: 'source-map',  // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
    module: {
        rules: [
            {
                test: /.css$/,   // 正则匹配以.css结尾的文件
                use: ['style-loader', 'css-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            },
            {
                test: /.(scss|sass)$/,   // 正则匹配以.scss和.sass结尾的文件
                use: ['style-loader', 'css-loader', 'sass-loader']  // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
            },
            {                             // jsx配置
                test: /(.jsx|.js)$/,   
                use: {                    // 注意use选择如果有多项配置,可写成这种对象形式
                    loader: "babel-loader"
                },
                exclude: /node_modules/   // 排除匹配node_modules模块
            }
        ]
    }
}
webpack4.x最详细使用讲解一第2张
// .babelrc 使用时把注释删掉,该文件不能添加注释
{
    "presets": ["env", "react"]
}
webpack4.x最详细使用讲解一第2张

此时不出问题的话应该一切运行正常,接下来让我们进入强大的插件模块。

https://www.cnblogs.com/BetterMan-/p/9867642.html

免责声明:文章转载自《webpack4.x最详细使用讲解一》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇redis持久化之RDBvue 验证码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

蓝天准系统P150em 980M 修改inf 安装451.67驱动

老机器,老显卡了。 但是980M是的硬件ID是特制的,需要修改,官网驱动说找不到硬件之类,无法安装 最近为了学pytorch,安装cuda10 重装系统。重新回忆一遍。 蓝天这个980M,在设备管理器里查看的硬件ID是 PCIVEN_10DE&DEV_13D7&SUBSYS_71021558&REV_A1 1 下载驱动 https:...

Linux的PCI驱动分析

1. 关键数据结构 PCI设备上有三种地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。CPU可以访问PCI设备上的所有地址空间,其中I/O空间和存储空间提供给设备驱动程序使用,而配置空间则由Linux内核中的PCI初始化代码使用。内核在启动时负责对所有PCI设备进行初始化,配置好所有的PCI设备,包括中断号以及I/O基址,并在文件/pro...

webpack 4.0 配置文件 webpack.config.js文件的放置位置

  一般webpack.config.js是默认放在根目录的,不在根目录的时候需要在package.json中制定位置,我的配置文件目录是config/webpack.config.js,在package.json文件中的配置为: "scripts": { "build": "webpack --mode production --config ./...

HDFS 命令深入浅出

HDFS 命令深入浅出~ [root@neusoft-master ~]# hadoop dfs Usage: hadoop fs [generic options][-appendToFile <localsrc> ... <dst>][-cat [-ignoreCrc] <src> ...][-checksum &l...

版本管理工具Git(三)Gitlab高可用

高可用模式 企业版 社区版 我们这里说一下成本比较低的主备模式,它主要依赖的是DRBD方式进行数据同步,需要2台ALL IN ONE的GitLab服务器,也就是通过上面安装方式把所有组件都安装在一起的2台机器。 什么是DRBD 它是分布式复制块设备,软件实现的无需共享可以在服务器之间镜像块设备的存储复制解决方案。 左侧为A节点,右侧为B节点 DRBD...

移动端 H5 拍照 从手机选择图片,移动端预览,图片压缩,图片预览,再上传服务器

前言:最近公司的项目在做全网营销,要做非微信浏览器的wap 站 的改版,其中涉及到的一点技术就是采用H5 选择手机相册中的图片,或者拍照,再将获取的图片进行压缩之后上传。 这个功能模块主要有这5点比较难:   1手机获取相册的图片文件,拍照的图片文件,通过js 的自带的img对象,获取图片对象。     2.图片的压缩,采用canvas 画布进行压缩图片,...