美文网首页
在webpack中这样分离环境和代码就好啦

在webpack中这样分离环境和代码就好啦

作者: 一颗冰淇淋 | 来源:发表于2022-05-29 20:06 被阅读0次

    前面的文章中,webpack.config.js 中包含本地调试和线上发布的所有配置,编译后的 bundle.js 包含所有的代码。

    当项目变大、代码量变多、配置增加的时候,文件的可维护性会越来越差,是时候对他们进行分离啦~

    环境分离

    环境分离主要是区分本地和生产两种环境,本地调试需要能实时看到代码变化,而生产环境需要编译成指定的文件。

    可以采用两种方式

    • 开发环境和生产环境分别定义配置文件,在 package.json 中定义对应的指令
    • 开发环境和生产环境共用配置文件,通过参数来区分环境

    配置文件分离

    分别定义用于开发环境的配置文件 webpack.dev.js 和用于生产编译的 webpack.prod.js,再分别通过 npm run servenpm run build来开启 devServer 和 编译操作

    // package.json
    "scripts": {
        "serve": "webpack serve --config ./config/webpack.dev.js",
        "build": "webpack --config ./config/webpack.prod.js",
      },
    

    参数区分

    开发环境和生产环境都使用 webpack.common.js 文件,通过 package.json 中设置指令增加 --env 参数来区分

    "scripts": {
        "serve2": "webpack serve --config ./config/webpack.common.js --env development",
        "build2": "webpack --config ./config/webpack.common.js --env production"
      },
    

    在 webpack.common.js 中 module.exports 定义为函数,就可以接收 env 传递的参数

    1_--env.png

    将开发环境和生产环境都需要用到配置抽离出来放到一个对象中,分别使用的配置分抽离到单独文件,再通过 webpack-merge 工具来对配置代码进行合并。

    // webpack.config.js
    const { merge } = require('webpack-merge');
    const devConfig = require('./webpack.dev');
    const prodConfig = require('./webpack.prod');
    const commonConfig = {
        ... // 公共要用的配置
    }
    
    module.exports = function (env) {
      // 赋值后可在 babel.config.js 中获取当前环境
      process.env.NODE_ENV = env.production ? 'production' : 'development';
      
      const config = env.production ? prodConfig : devConfig;
      return merge(commonConfig, config);
    };
    

    这样公共配置部分就可以统一管理

    2_webpack-common-js.png

    代码分离

    所有源代码都编译到一个文件中,会造成编译文件过大,一次性加载所有资源,加载速度慢,从性能的角度来思考,希望提升请求速度,以及当资源需要的时候再加载,那这个时候可以根据功能将源代码编译成多个文件。

    代码分离有三种方式

    • 多入口:通过 entry 配置多个入口,手动分离代码
    • 防止重复:使用 Entry Dependencies 或 splitChunksPlugin 去重和分离
    • 动态导入:通过 import 函数来分离

    多入口

    // webpack.config.js
    // 获取启动目录
    const dirname = process.cwd();
    const resolveApp = (folder) => path.resolve(dirname, folder);
    
    module.exports = {
        entry: {
           index: './src/index.js',
           main: './src/main.js',
        },
        output: {
           filename: 'js/[name].js',
           path: resolveApp('./dist'),
        },  
        // ...
    }
    

    这样编译后就会根据入口生成两个js文件

    3_多入口.png

    防止重复

    当存在公共的库时,多处引用可能会造成重复加载的问题。

    Entry Dependencies

    一种方式是定义 entry ,将重复的依赖抽离单独编译成一个文件

    4_抽离依赖文件.png
    splitChunksPlugin

    另外就是可以使用 splitChunksPlugin, 它已经默认集成在 webpack 当中,通过 splitChunks 来设置属性,chunks 属性有三个值,用于定义分离的场景。

    • async,默认情况,只有当代码进行异步操作时才会分离
    • initial,同步代码会分离
    • all,异步同步都会分离
    optimization: {
      chunkIds: 'named', // 规定文件的命名方式
      splitChunks: {
        chunks: 'all',
      },
    },
    

    定义了 splitChunks 中分离代码方式之后,在 index.js 中使用到的 moment 和 lodash 都编译到 vendors 这个文件中

    5_chunks-all.png

    splitChunks 中还有其它的属性,用于规定编译的文件大小、文件名

    • minSize,默认2万字节,规定拆分出来的包最小值
    • maxSize,规定大于 maxSize 尺寸的包,拆分成不小于 minSize 的包
    • minChunks,表示引用的包至少被导入的次数
    • cacheGroup,缓存组,配置具体的编译规则

    这些即使不设置,也都是有默认值的,上面将依赖打包的非常长的文件名 vendors 就是按照默认的设置生成的,在 webpack 的官方文档 中有介绍

    6_splitChunks的默认值.png

    也可以自己再进行定义,比如更改 打包依赖的文件名

    7_自定义vendor文件名.png

    动态导入

    另外一种分离的方式就是动态导入了,当使用资源时,才会下载并解析。

    以下代码在 index.js 中引入 foo.js 和 baz.js

    import('./foo');
    import('./baz');
    

    通过 import 函数动态导入的 js 被编译成两个单独的文件。

    8_import动态导入.png

    动态导入还可以通过魔法注释做一些配置

    • webpackChunkName 自定义编译后文件名
    • webpackPrefetch 在浏览器空闲时提前下载资源
    • webpackPreload 和父 chunk 一起提前下载资源

    在 import 函数中定义魔法注释

     import(
        /* webpackChunkName: 'foo'  */ /* webpackPreload: true */ './foo.js'
      ).then((result) => {
        console.log('foo加载了', result, result.default);
      });
    

    可以在看到 foo.js 第一次是在浏览器空闲时下载资源,第二次是从缓存中获取资源

    9_webpackPrefetch.png

    使用 prefetch 预获取的方式可以提前下载好资源,当使用的时候速度会相对快一点,但这样会给入口文件渲染增加压力,所以还得视实际使用场景而定。

    总结

    • webpack.config.js 中使用 module.exports 导出函数,通过参数来区分编译环境,从而使用不同的 loader、plugin 和配置来处理开发、生产环境的资源。

    • 拆分代码可以通过多入口 entry 、防止重复 splitChunksPlugin 和动态导入 lazy 函数的方式来操作,其中动态导入异步文件可以设置预加载或者预获取提前下载资源。

    以上就是 webpack 环境和代码分离的相关介绍, 更多有关webpack的内容可以参考我其它的博文,持续更新中~

    相关文章

      网友评论

          本文标题:在webpack中这样分离环境和代码就好啦

          本文链接:https://www.haomeiwen.com/subject/vvbpprtx.html