webpack基础:从零搭建项目框架

539 阅读5分钟

前端的小伙伴们对webpack太熟悉不过了,今天这篇文章作为webpack深入浅出系列的第一篇,就直奔主题,记录一下一个项目搭建起来的过程吧。

最简单的webpack例子

我们通常说webpack是一个JavaScript打包工具,那非JavaScript是如何进行打包的呢,在我这一系列的文章中会慢慢解答。但是百里之行始于足下,我们需要先看看webpack是如何做好自己的本职工作的。

webpack config

webpack可以免配置打包,但是一般情况下,我们会提供一个配置文件。在这个简单的例子中我会提供这么一个简单的文件供大家参考:

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

这份配置里面的几个关键点其实大家都挺清楚,mode是指定打包环境的,production在webpack官方文档中描述是:会将DefinePlugin中的process.env.NODE_END的值设置为'production'。为模块和chunk启用确定性混淆名称,FlagDependencyUsagePlugin,FlagIncludeChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin和Terserplugin。

entry和output分别是入口和出口。

项目文件目录

现在这个示例项目的文件项目目录是这样的:

my-package

  • node_modules
  • package.json
  • yarn.lock

我们把刚才那个配置添加进去,在根目录下创建'webpack.config.js',将刚才的代码复制进去。

创建打包资源

此时在项目下创建src目录,并在目录下创建两个文件: helloWorld.jsindex.js

// helloWorld
export default {
    webpack: 'is good'
}
// index.js
import helloworld from 'helloWorld.js'
console.log(helloworld.webpack)

在命令行输入:npx webpack或者./node_module/.bin/webpack命令。

在目录下会生成dist文件夹,将里面的bundle.js(我们会在下一篇文章分析这个文件)复制到任意页面中,打开页面在控制台就会得到想要的结果。

总结

这是最简单的一个打包示例,我们可以初步体验下webpack创建打包的步骤。在接下来的文章中,我们在看下如何将页面常见的资源打包进项目中。

其他资源

ES6的解析

其实webpack本身功能特别有限,但是官方以及社区为webpack开发出了很多插件。如果多说两句,实际上webpack和gulp之间只是流程上的区别而已,有想法的朋友其实可以用gulp作出一款类似webpack的工具。 言归正传,对高级语法的解析都是通过babel-loader实现的。www.babeljs.cn/ 是babel的官网,我也会出一期文章专门整理一下babel的入门(貌似给自己挖了一个坑)。 在webpack中使用babel需要经过以下几步:

  1. 创建babelrc文件(可以是json文件也可以是js文件);
// .babelrc.js
module.exports = {
    "presets":[
        "@babel/preset-env"
        "@babel/preset-react"
    ]
}
  1. 在webpack配置中设置babel-loader的相关配置;
// webpack-config
{
    // 注释无关代码
    module: {
        rules: [
            {
                test: /.js$/,
                use: "babel-loader"
            }
        ]
    }
}

这样,再次打包的时候,babel就会将代码编译成浏览器能运行的语法形式了。

CSS解析

解析css需要至少两个loader才能完成,分别是:

  1. css-loader 用于加载.css文件,转换成commonjs对象;
  2. style-loader 将样式通过style标签插入到head中; 为了能够使用css预处理器,我们可能还会安装相对应的插件,比如less;
yarn add css-loader style-loader less less-loader -D

然后配置文件里写好对应的配置。

{
    test: /.css$/,
    use: [
        'style-loader',
        'css-loader'
    ]

},
{
    test: /.less$/,
    use:[
            'style-loader',
            'css-loader',
            'less-loader'
        ]
    }

图片和文字

处理图片和文字的loader是url-loader,和file-loader一样,它能够解析图片和字体资源,不同的是,他可以指定资源的一个大小,如果资源实际大小小于这个值就会被处理成为一个base类型的资源。由于url-loader内部还是依赖了file-loader,需要一同安装。

    {
        test: /.(jpg|png|gif|jpeg)$/,
        use: {
            loader: 'url-loader',
            options: {
                limit: 1024
            }
        }
    }

HTML相关

当js,css,图片等必须的资源都处理结束之后,就要将他们想办法和html建立联系,这样我们就能在打包完成之后直接扔到服务器上进行访问了。

HtmlWebpackPlugin,这是一个plugin,用来将html模版输出到打包好的文件夹下,与其他资源一起进行发布。

plugin在webpack中很重要,他可以设定在不同的打包过程中进行一些操作,不仅限于输入和输出,也不仅限于处理文件。总之很强大,在HtmlWebpackPlugin中,可以进行代码的压缩处理。

{
    plugins:[
        new HtmlWebpackPlugin({
            template: '项目入口html的文件',
            filename: '自定义项目html名称',
            minify: '压缩相关'
        })
    ]
}

基础部分总结

通过上述配置,一个基本的脚手架就搭建完成了,满足了最基本的开发需求,但是,随着项目越来越大,这个配置的弊端就会暴露出来。 接下来我们看一下如何进阶一些使用。

进阶用法

之前的配置中,我们每次构建之后构建目录都是追加的内容。这样我们的构建目录就会越来越庞大,不仅占用很多资源,也影响着我们的维护。

px2rem

我们在开发移动设备的时候,通常会遇到一个常见的问题:由于手机分辨率的不同,我们写的同一套css字体,元素宽高等样式会出现一些兼容性的问题,典型的就是在一些设备上正常显示,在另一些设备上就会出现过大或者过小。为了解决这个问题,我们可以对我们的css样式进行一些自动化的修改,结合浏览器的一些特性,使得我们写一套样式可以自动转为按照比例控制大小,这样就可以解决兼容问题。

解决这个问题有两个关键点, 一、将字体大小转化为rem,本质上就是将绝对的单位转化为相对的单位,rem会根据根元素的字体大小进行自动计算。 二、设置根元素字体大小,按照不同机型计算出根元素字体大小才能最适配当前机型。

以上两点分别由:px2rem-loader和自定义方法完成。

{
    test:/.less$/,
    use: [
        'style-loader',
        'css-loader',
        'less-loader',
        {
            loader: 'px2rem-loader',
            options: {
                remUnit: 75,
                remPrecision: 8
            }
        }
    ]
}
 // 计算页面根元素字体size
 var width = window.innerWidth / 375 * 16 + 'px';

静态资源内联

静态资源内联的含义就是将一些通用的资源做成通用库,然后借助工具将他们内联进html的对应代码。这个工具在webpack中可以是loader也可以是plugin,比较简单,通常可以用row-loader。

sourcemap

sourcemap一般不建议在生产环境中使用,如果确实需要排查问题,建议将其上传到cdn中去,这样的话不会影响正常的业务包的大小。

TreeShaking

treeShaking在webpack中是默认开启的,且仅支持新版本的ES语法。他会将代码中没有使用到的部分‘摇掉’,不会进行打包。 主要运用了es6模块的静态引入的特点进行功能实现。 摇树会作用于没有用到的模块、方法和变量。

代码分割

在webpack中有一个特别重要的配置,叫做optmization,这个配置可以用来将公用的代码抽取出来同时支持将过大的chunk分割成小的chunk。从而起到减小chunk体积的作用,是我们常用的代码优化的手段。

{
    optmization: {
        splitChunks: {
            chunks: '进行优化的chunk类型',
            minSize: 'chunk的最大体积',
            maxSize: 'chunk的最大体积',
            minChunks: '拆分前被共享的最小chunk数',
            maxAsyncRequests: '按需加载时最大的请求数',
            minInitialRequest:'入口点最小并行请求数',
            automaticDelimiter: '用来分割名称的符号',
            name: 'chunk名称是否保留之前的名称',
            cacheGroups:'将分离的代码进行分组,这里的条件完全继承上一层的所有属性'
        }
    }
}

代码规范

代码规范是我们写好代码的保证,为我们的代码提供了可维护性。 保证代码规范的方式有很对,可以是webpack,也可以使用编辑器插件,但是后者的操作性就差一些。这里就说一下在webpack中如何实现代码规范检查吧。 想让代码规范生效,eslint需要首先设置一个eslintrc文件,这个文件定义了eslint的审核规则。

eslint除了检查代码,也可以帮助开发者自动格式化代码,这个功能是可选的。 同时自动美化代码还可以使用prettier,这是专门用来进行代码规范的工具。 另外,一般会在配合一个husky来进行git配合,设置pre-commit的检查点。 这样,就能在提交之前发现和修改代码中不符合规范的地方。

{
    module:{
        rules:[
             {
                 test: /.(js|jsx)$/,
                 use: 'eslint-loader'
             }
        ]
    }
}

可以设置这个loader在其他loader之前进行,这一点小伙伴们应该知道怎么设置,不知道的就去查一下文档吧。

总结

自此,webpack基本使用和优化我们都已经学会了,日常使用对于我们来说应该不成问题了。遇到一些打包问题也可以独立分析了。

下一篇预告

本篇文章仅仅是用于抛砖引玉,小伙伴们在这个之上应该可以更多的探索我没有讲到的问题。下一篇文章,我会分享一下如何进行loader和plugin的编写和分享一下webpack原理。希望对小伙伴们有所帮助。