webpack新手系列-1.初尝webpack

288 阅读3分钟

引言:webpack以其强大且全面的功能在前端工程化构建的道路上大放异彩,有着丰富的社区生态,深受前端开发者的青睐,又正是因为其功能强大,接口丰富,扩展性强的特点,导致许多未接触过打包的新人(尤其是未经历过grunt,gulp阶段的)在入手webpack之初,看着如此繁多API及对应功能,有些头昏脑涨,本系列在此梳理关于webpack打包构建的脉络,很好的使用对应的打包技巧。

webpack是什么?

要使用webpack,首先要理解webpack是什么,根据官网首图介绍

就是将各种资源分门别类,整理成对应的js,图片,css资源,这就是webpack最核心的功能。因为前端页面就是通过样式,图片资源,JS脚本构成的,但是由于页面越来越复杂,资源引用,代码引用,样式引用等会变得越来越复杂,因此,webpack帮忙整理,最后生成有条理的资源,在提高开发效率的同时,也减少某些问题的发生。

webpack.config.js

webpack的基本配置文件,webpack有两种构建方式,一种是通过命令,另外一种是同构配置文件 webpack.config.js 通常情况下使用第二种,功能完善且易用性强**。**在构建时,webpack会自动识别该文件,并根据相关配置进行构建。

module.exports = {
    entry: './src/index.js',
    ouput: {
        path: path.join(__dirname, './dist'),
        filename: bundle.js    
    },
    mode: 'production'
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'                
                ]            
            }        
        ]          
    },
    plugins: [ 
        new xxxPlugin()
    ]    
}

webpack主要知识点:

根据webpack.config.js配置文件,有主要以下几个知识点:

  1. entry
  2. output
  3. mode
  4. loader
  5. plugin

1.entry

构建的入口打包的源头

如官网图所示,作为主要文件的入口,在入口文件中会引用别的文件,而别的文件又引用许多别的文件,因此,入口就相当于一个线头,根据这个线头,把所有缠在这根线的其余线给解开并分类。

配置相关:

// 单入口打包构建
entry: './src/index.js',  // 以单一字符串的形式
// 多入口打包构建
entry: {
    index: './src/index.js',
    test: './src/test.js'
} // 以map的 key-value 形式确定入口

2.output

webpack打包后的输出,既将整理并分类好的各种类型的内容文件存放的地方。

output: {
    path: path.join(__dirname, './dist'),
    filename: bundle.js | [name]_bundle.js,
    // filename里面对应不同的打包方式
    // 前者为单页应用,一般也只是单文件输出
    // 后者为多页应用,根据entry对象的key作为 [name] 的占位符如 index_bundle.js, test_budle.js
}

3.mode

mode: 'production' | 'development' | 'none' 
// 不同模式底下所集成的功能不同,
// 如:production 默认集成了uglifyjs,tree-shaking, hoisted-scope等功能

4.loader

由于webpack是在Node环境底下运行的,只能识别 JS 和 JSON 语言的内容

但是在前端里面还有类似CSS,图片资源,字体资源等相关内容,对于这些webpack不能识别的内容,需要将其转换为JS模块

loader就是这样的一个转换工具

loader本身其实就是一个函数,接受一个文件输入,将其转换为JS或者JSON输出

// loader 的本质
function loader(sourcefile) {    // change the file to js code
    const jscode = changeFile2JS(sourcefile);
    return jscode;
}

loader配置,需要配置在module里面的rules,一种文件的匹配需要对应相关的loader

module: {
    rules: [
        {
            test: /\.js$/,
            use: 'babel-loader'  // 如将ES6通过babel转换为ES5        
        },
        {
            test: /.css$/,
            use: [
                'style-loader',
                'css-loader'                            
            ]
            // 用到多个loader用数组,loader的执行顺序由后往前,
            // 即先执行css-loader转换css文件
           // 而后使用style-loader 将其插入到 head 的 style 标签中                }    
    ]
}

5.plugins

在整个webpack构建过程中,如构建开始,构建中,构建结束,生成构建产物等节点,webpack会有钩子抛出,而plugin就可以接入这个钩子,在对应的时间节点执行相应的功能,这样就相当于扩展了webpak的额外功能

将webpack整个构建过程比喻成一个制作 玩具的流水线,没有plugin的话,其最终可以制造出一个普普通通的玩具,没有美感,也没有太多的功能,但它的确是一个能玩的玩具

但是在制作的流水线上,有不同的工位,这些工位就好比plugin,如果说玩具注塑完成的地方有一个上颜色的工位,该工位可以让玩具具备各种各样的颜色,然后到最后完成的地方也有一个工位

打包装,这样玩具又有了漂亮的外壳包装。总而言之,这些plugin就是这些工位,在打包构建整个过程中,根据抛出的钩子,扩展出各种各样的功能。

plugins: [
    new HtmlWebpackPlugin()
]

还可以根据自己的需要编写对应的plugin

通过webpack打包一个简单项目

了解并知悉了以上5个功能对应的知识点,其实就可以用webpack构建一个简单的项目了。

安装webpack

mkdir webpack && cd webpack  // 新建一个webpack目录
npm init -y
// 生成一个package.json 文件,初始化项目

npm i webpack webpack-cli -D // 安装webpack 及 webpack 脚手架

新建src文件夹及添加index.js文件,新建webpack.config.js配置文件

得到如下项目目录

首先在package.json里面添加build打包命令

"script" : {
    "build": "webpack"
}

配置webpack.config.js

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.join(__dirname, './dist'),
        filename: bundle.js    
    },
    mode: 'production',
}

执行构建

最简单的一个打包,甚至不将 es6 转换为 es5

index.js文件如下:

export function helloworld() {
    const map = {
        hello: 'hello',
        world: 'world'
    };
    const { hello, world } = map;
    return `${hello} ${world}`;
}

document.write(helloworld());

这里故意用了 es6 的语法,执行 npm run build 看下打包出来之后的产物是啥

可以看到通过配置output输出到了dist文件夹,同时文件名称为bundle.js

bundle.js

(()=>{"use strict";document.write(function(){const{hello:l,world:o}={hello:"hello",world:"world"};return`${l} ${o}`}())})();

可以看到这里的代码被压缩了(这个就是mode为production集成的功能),同时还是 es6 的语法,并没有作任何改动;

babel-loader

前文提到loader的作用,就是将各种文件转化为JS文件,同样的由于es6 并没有完全被兼容,所以这里要把 js 文件通过babel 把 es6 转换为 es5。

babel的具体功能可翻阅官网文档

那么需要用到以下几个包

@babel/core @babel/preset-env @babel-loader

npm i @babel/core @babel/preset-env @babel-loader -D

同时还需要创建babel配置,用官方推荐的 .babelrc

.babelrc 配置

{
    "presets": [        ["@babel/preset-env"],  // 将 es6 转换为 es5
        // "@babel/preset-react" 如果要将react转换的话,
        // 则需要这个,同理,其余的要转换,也要安装对应的包    ],
    plugins: []
}

此时执行npm run build

将会得到dist文件,其中的bundle.js文件

(()=>{"use strict";document.write(("world","".concat("hello"," ").concat("world")))})();

显然看到这里的转换跟之前不太一致,这里已经转换为通用的es5了

至此,一个最简单的webpack打包,便已完成。

总结

webpack功能虽然强大繁多,但是抓清其主要打包脉络,使用起来也不会说太复杂。

熟悉主要几个概念:

  1. entry
  2. output
  3. mode
  4. loader
  5. plugin

并通过webpack.config.js配置文件进行一个简单的项目打包,了解这几个概念是如何起作用的。

但要想构建一个更加现代化的前端项目,光了解这些内容,还是不够的,请期待下一篇:

webpack打包系列-2.react项目打包及图片样式资源引入