【webpack浅析】webpack之深入浅出

前言

本文旨在讲解webpack的基本配置。从0开始,由浅入深地讲解webpack是如何工作和配置的,一步一步的带你揭开webpack的神秘面纱。

如有纰漏,敬请指正。

目录

深入了解webpack

1、webpack干什么的

2、webpack的核心概念

3、从0开始配置项目

webpack配置 - 处理文件类型

webpack配置 - 前端工程自动化配置

webpack配置 - 结合vue


深入了解webpack

1、webpack干什么的

总的来说,webpack是一个 资源综合处理中心 。为了说明这个处理中心,这里我要利用一张图片(见配图 1.1)大概齐的解释一下webpack。webpack 其实可以看做是一个半自动(之所以是半自动,是需要我们自己进行很多的配置)工厂流水线。所有的前端资源,比如 图片,样式,js文件等等,一个接一个排好队伍,整齐划一的进入流水线,根据设定好的程序(就是webpack的那些配置),一一处理加工(根据各种module规则的配置进行解析,根据一些plugins进行压缩等等的处理),生产出最终的产品(也就是我们的dist包,里边包含我们处理好的前端项目资源)。

2、webpack的核心概念

毫不夸张的说,webpack的配置项没有一万也有八千。如果将每一个API都研究透彻,伤神费力效率低。所以,看问题,要看本质,而看本质,就要抓住核心。那么 webpack的核心模块和配置主要有哪些? 这里列举了几个主要的:

  • entry 

官方文档:https://www.webpackjs.com/configuration/entry-context/#entry

entry:是webpack的入口,这里配置项目入口文件的地址。由此开始进入webpack的构建流程。

  • output

官方文档:https://www.webpackjs.com/configuration/output/

output:输出资源的信息配置,包含输出资源的文件名(filename),输出资源的放置路径(path)等等。

  • module

官方文档:https://www.webpackjs.com/configuration/module/

module:里边规定了如何去解析和转义各种文件类型(主要是 rules loaders配置)。

  • resolve

官方文档:https://www.webpackjs.com/configuration/resolve/

resolve:制定了如何去寻找模块依赖。(比如指定 alias 来简化文件路径 )

  • plugins

官方文档:https://www.webpackjs.com/configuration/plugins/

plugins:在某个时机(生命周期)去对资源进行操作的方法。

以上几部分,就是webpack最核心的部分。

下面我们从0开始,配置和使用webpack来处理和打包。

3、从0开始配置项目

我们来通过一个项目,一个一个的介绍这些项目如何配置和工作的。


// 创建一个文件夹 里边执行
npm init -y

// 得到package.json,在文件夹中安装 webpack webpack-cli
npm i -D webpack webpack-cli

// 根目录创建 webpack.config.js 文件

项目结构如下:

默认情况下,webpack.config.js 代表webpack的配置。当然文件名也是可以更改的,通过 webpack 命令进行更改:

webpack --congfig xxxxx(你自己的文件名,比如webpack.my.config.js)

webpack配置 - 处理文件类型

文件中添加src文件夹,里边首先来一个主文件,也就是 入口文件 main.js, 然后再来一个js文件夹,写两个简单的方法,目的是引入main.js,就像这样:

在 入口文件中引入:

import {
add
} from './js/math'

console.log(add(1, 2));

最简单的入口文件已经完成了。

A、处理 js文件

开始配置webpack.config.js:

module.exports = {
    // entry 入口文件
    // 告诉 webpack 要解析这个文件中引入依赖和资源

    entry: './src/main.js'
}

有了入口,就应该想到出口 output:

const path = require('path');

module.exports = {
    entry: './src/main.js',
    
    // 出口
    output: {
        
        // 设置打包生成文件的名称以及文件路径
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
}

现在最基本的webpack配置已经完成。我们准备执行一下,看看结果。

怎么执行呢?

其实三种执行办法:

  • webpack

  • npx webpack

  • scripts

在package.json中的scripts配置脚本:

{
  "name": "webpack_demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12"
  }
}

最后一种方式是不是让你想起了 npm run dev.(笑脸.jpg).

既然如此,我们将在后边都是用 脚本方式

我们看到上图,最终的结果终于是打包成功了。

验证一下吧,在生成的dist文件中手动添加一个  html文件,把生成的bundlejs引入,在浏览器中看看吧。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <script src="./bundle.js"></script>
</body>
</html>

执行一下,结果为

嗯,不错,验证成功,说明这个打包都没错。

到目前为止,我们没有任何处理关于js文件的配置。这正好印证了webpack是天生处理js文件的好帮手。但是我们知道,还有更高阶的js呢,比如 ES6,甚至ES10。这些高阶的写法,除了chrome等少数浏览器很好的支持,还有一些浏览并不能很好的支持。那么这时候我们需要将这些高阶的写法转化为更加兼容的写法。所以,这时候又要提到了babel。

要使用babel,首先要安装babel-loader。

npm i -D babel-loader

当webpack使用babel-loader处理文件时,babel-loader实际上调用了babel-core的api,因此也必须安装babel-core:

npm install -D babel-core

babel有几种规则都可以实现对ES6语法的转码,如babel-preset-es2015、babel-preset-latest、babel-preset-env,要安装babel-preset-env的作用是告诉babel使用哪种转码规则进行文件处理:

npm install -D babel-preset-env

注意:babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'duse Babel 6.x ('babel-core'), you should install 'babel-loader@7'. 就是说注意你的babel-core和babel-loader要匹配。否则报错。

在package.json中配置规则:

...

"babel": {
    "presets": [
      "env"
    ]
  },

...

在webpack.config.js中配置loader:

...


{
   test: /\.js$/,
   exclude: /node_modules/,
   use: ['babel-loader']
},

...

这样成功处理js文件。(如果需要验证,找一个IE低版本浏览器,写一些promise等语法进行验证,看看是否能打包成功

B、处理css文件

很显然,前端资源不仅仅只有js文件。还有css文件。我们在文件中写个css文件,并引入入口文件中。

执行一下,毫无意外的报错了。报错信息很明显:You may need an appropriate loader to handle this file type。

直接告诉你,你需要一个合适的 loader 来处理这类型的文件。什么loader? 当让是css-loader,style-loader。

// 处理css 需要用到style-loader css-loader
// 安装吧

npm i -D style-loader css-loader

安装完毕之后,又要配置loader了。

let path = require('path');

function resolve (url) {
    return path.resolve(__dirname, url)
}

module.exports = {
    entry: './src/main.js',
    output: {
        filename: 'bundle.js',
        path: resolve('dist')
    },
    // 开始配置loader
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    }
}

这里要注意:loader的解析顺序是从后往前。

先交给 css-loader 处理css文件,处理完成之后再交给 style-loader处理,然后动态的向我们的html文件的head中添加style标签,注入css,最终就像这样的:

 

现在css文件也成功的处理好了。

C、处理图片文件

现在我们准备在引入图片资源。

为了方便,在css文件中引入一个背景图片。

我们可以直接打包。不过,也许你因为上边css-loader而变得有先见之明。这次也一定会报错。所以,我们同样的要安装处理图片资源的loader。

// 处理图片类的loader有两个: url-loader和file-loader
npm i -D url-loader file-loader

这一次又是两个loader。但是和css处理的不同。他们两个的只需要其中的一个即可。虽然功能差不多,但是他们还是有一些区别:

1、请记住,url-loader依赖于file-loader。如果用url-loader,一定要安装 file-loader。

2、url-loader处理文件时,可以设置文件大小限制(limit)。如果图片文件小于这个限制,就会被直接处理为base64形式。大于这个限制,就会直接输出到指定文件中。

好了,我们来配置一下处理图片的loader:

const path = require('path');

function resolve(dir) {
    return path.resolve(__dirname, dir)
}

module.exports = {
    ...


    module: {
        rules: [
           
            ...

            // 图片的配置
            {
                test: /\.(png|jpe?g|gif)/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            // 小于8k的图片将被转为base64
                            limit: 8192,
                            // 输出的文件名字
                            name: '[name].[hash:8].[ext]',
                            // 输出的路径
                            outputpath: 'images/'
                        }
                    }
                ]
            }
        ]
    }
}

打包验证一下:

 如上,图片也成功打包成功。小于8k成功被处理为base64。实际上,这两个loader不仅仅用来处理图片,同时也可以处理多种格式的文件,比如 pdf,ttf等。

webpack配置 - 前端工程自动化配置

A、HtmlWebpackPlugin

我们每次验证的时候都得自己手动的在 dist 包内添加index.html,手动引入 bundle.js。这样做真的很不智能,很不科学。有个插件j叫 HtmlWebpackPlugin。能帮助解决这个问题,他就是在打包之后拷贝一份src目录下的indexhtml,自动引入bundle.js。

安装一下吧:

npm install --save-dev html-webpack-plugin

在webpack.config.js中配置使用:

// webpack.config.js

// 引入htmlwebpackplugins
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exportd = {

    ...

    plugins: [

        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
}

构建一下试试:

看看,成功的拷贝了一份index.html,并引入 bundle.js。 

B、webpack-dev-server

另外可能你也注意到了,每一次构建的时候都是直接打包的。但是我们在实际的开发环境下,不需要每次打包出dist,而是希望生成资源后,在浏览器打开index.html。那么个时候需要用到webpack-dev-server。

首先得安装webpack-dev-server:

npm i -D webpack-dev-server

在webpack.config.js中配置dev-server:

module.exports = {
    ...


    devServer: {
        // 告诉服务器从哪里提供内容
        contentBase: path.join('dist'),
        // 是否开启压缩
        compress: true,
        // 端口号
        port: 9999
    }
}

做了这些基础的配置,我们还需要在 package.json 中配置一下启动脚本以便支持我们的 npm run dev 和 npm run build。

...

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server",
    "build": "webpack"
},

...

然后 npm run dev:

构建成功。并且看到该项目已经运行在了 我们配置的 9999 端口,在浏览器中打开:

 自动的打开index.html,一切都正常。

那我现在想要在项目中改变一下box的样式:

改变index.css中的背景色: background: #096。

成功变成了颜色。

C、HMR(热更新)

但是这样有个问题。每次变化了,webpack-dev-server会整体刷新页面,造成效率低下。这时候就需要引入热更新的概念了 - HotModuleReplacementPlugin(简称 HMR)。

这个插件是webpack内置的不需要额外安装,配合 devServe中的hot配置项,就可以实现。在webpack.config.js中做出一些改变:

// 引入 webpack
const webpack = require('webpack')


module.exports = {
    

    ...


    plugins: [

        ...


        // 引入热更新模块
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 9999,
        

        // 开启热更新
        hot: true

    }
}

npm run dev ,打开localhost:9999成功打开页面。现在更改一下css文件,看看热更新有没有起作用。把index.css中的 box的背景色改变为 #d02;然后看看页面成功更新如下:

 热更新也成功部署完毕了。

webpack配置 - 结合vue

上边大概介绍了一下前端工程使用webpack进行构建的过程。下面结合vue前端js框架,看看vue和webpack如何让结合。

首先肯定要安装vue

// 安装 vue
npm i -S vue

vue这种类型的文件,浏览器肯定不认识。仍然是需要loader去转义解析一下的,所以在安装 vue-loader

npm i -D vue-loader

另外还需要安装一个编译loader叫做vue-template-compiler,目的是把vue的template模板语法编译为render函数,以更高效的进行构建。

npm i -D vue-template-compiler

安装工作暂时告一段落。下面开始配置webpack.config.js:

module.exports = {
    ...


    module: {
        rules: [

            ...


            // 新增vue-loader解释器

            {
                test: /\.vue$/,
                include: resolve('src'),
                use: ['vue-loader']
            },
        ]
    }
}

然后准备开始在入口文件中引入 vue,在引入vue之前需要src下创建一个App.vue文件,方便一会vue渲染。

然后开始改变入口文件,引入vue,并挂载到index.html中id为app的根节点上:

// 入口文件 main.js

import Vue from 'vue'

import App from './App.vue'

new Vue({
    el: '#app',
    render: h => h(App)
})

给index.html中添加一个id为app的div根节点:

 看起来应该是可以了吧,直接 npm run dev 看看:

报错了。报错信息:vue-loader was used without the corresponding plugin.大概意思是 vue-loader在没有合适插件的情况下被使用了。也就说使用vue-loader还得要个插件,就是它 - VueLoaderPlugin。需要引入这个插件才能使vue-loader正常使用。好吧,配置一下plugins:

// webpack.config.js


// 引入VueLoaderPlugin
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    ...


    plugins: [

        ...


        // 配置vue-loader 需要使用vueloaderplugin
        new VueLoaderPlugin ()
    ]
}

重启服务。npm run dev ,打开localhost: 9999;

 大功告成了。然后就开始享受你的vue项目吧。

深入浅出webpack的配置,写到这里基本就准备结束了。webpack的博大精深,本文提及的不及万一。所以大家还是没事多看看官方文档。

最终附上源码地址供参考之用: https://gitee.com/gitee__wang/basic_configuration_of_webpack

end~

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值