webpack打包流程


https://www.cnblogs.com/tugenhua0707/p/4793265.html

https://blog.csdn.net/qq_35480270/article/details/88775849

https://blog.csdn.net/loveer0/article/details/82257929

https://zhuanlan.zhihu.com/p/150731200

https://segmentfault.com/a/1190000015883378

webpack打包原理

webpack性能优化

1、webpack打包原理

把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载。

2、webpack的优势

(1) webpack 是以 commonJS 的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。

(2)能被模块化的不仅仅是 JS 了。

(3) 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。

(4)扩展性强,插件机制完善

3、什么是loader,什么是plugin

loader用于加载某些资源文件。因为webpack本身只能打包common.js规范的js文件,对于其他资源如css,img等,是没有办法加载的,这时就需要对应的loader将资源转化,从而进行加载。

plugin用于扩展webpack的功能。不同于loader,plugin的功能更加丰富,比如压缩打包,优化,不只局限于资源的加载。

4、什么是bundle,什么是chunk,什么是module

bundle:是由webpack打包出来的文件

chunk:是指webpack在进行模块依赖分析的时候,代码分割出来的代码块

module:是开发中的单个模块

5、webpack 和 gulp 的区别?

webpack:

webpack是一个模块打包器,强调的是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源都看成是模块,通过loader和plugin对资源进行处理。

gulp:

gulp是一个前端自动化构建工具,强调的是前端开发的工作流程,可以通过配置一系列的task,第一task处理的事情(如代码压缩,合并,编译以及浏览器实时更新等)。然后定义这些执行顺序,来让glup执行这些task,从而构建项目的整个开发流程。自动化构建工具并不能把所有的模块打包到一起,也不能构建不同模块之间的依赖关系。

6、什么是模热更新?有什么优点?

模块热更新是webpack的一个功能,它可以使得代码修改之后,不用刷新浏览器就可以更新。在应用过程中替换添加删出模块,无需重新加载整个页面,是高级版的自动刷新浏览器。

优点:

只更新变更内容,以节省宝贵的开发时间。调整样式更加快速,几乎相当于在浏览器中更改样式

7、webpack-dev-server 和 http服务器的区别

webpack-dev-server使用内存来存储webpack开发环境下的打包文件,并且可以使用模块热更新,比传统的http服务对开发更加有效。

8、什么是长缓存?在webpack中如何做到长缓存优化?

浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或者更新,都需要浏览器去下载新的代码,最方便和最简单的更新方式就是引入新的文件名称。

在webpack中,可以在output给出输出的文件制定chunkhash,并且分离经常更新的代码和框架代码,通过NameModulesPlugin或者HashedModulesPlugin使再次打包文件名不变。

9、什么是Tree-sharking?CSS可以Tree-shaking吗?

Tree-shaking是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码。在webpack中Tree-shaking是通过uglifySPlugin来Tree-shakingJS。Css需要使用Purify-CSS。

有关vue项目中,@默认src的问题

在Vue项目中,@符号默认指向src目录。

这是通过webpack配置文件中的alias别名来实现的。这样做的好处是可以更方便地引用src目录中的文件,而不需要使用相对路径。

在大多数情况下,@不需要额外手动配置,vue-cli会定义。

Vue CLI 在创建项目时会自动配置好这个别名。如果你使用的是 Vue CLI 创建的项目,那么默认情况下,@符号就会指向src目录。

但是,如果你使用的是手动配置的Vue项目,那么你可能需要在webpack配置文件中手动添加这个别名。你可以在webpack配置文件中的resolve.alias中添加以下内容:

const path = require('path')
/**
 * __dirname:当前文件夹所在的绝对路径
 */
const resolve = (dir) => path.join(__dirname, dir);//或 path.resolve(__dirname, dir)

module.exports = {
    configureWebpack: {
        resolve: {
            alias: {
                '@': path.resolve(__dirname, 'src')
            }
        }
    },
    //或
    chainWebpack: (config) => {
        config.resolve.alias
            .set("@", resolve("src"))
            .set("@static", resolve("public/static"))
    }
}

vue.config.js里chainWebpack和configureWebpack有什么区别

官网定义:

  • configureWebpack:

如果这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中。

如果这个值是一个函数,则会接收被解析的配置作为参数。该函数既可以修改配置并不返回任何东西,也可以返回一个被克隆或合并过的配置版本。

如果你需要基于环境有条件地配置行为,或者想要直接修改配置,那就换成一个函数 (该函数会在环境变量被设置之后懒执行)。该方法的第一个参数会收到已经解析好的配置。在函数内,你可以直接修改配置,或者返回一个将会被合并的对象。

configureWebpack 不支持 vue cli 的语法糖或者说是不支持链式编程配置形式。只能通过操作对象的形式,来修改默认的 webpack 配置。

configureWebpack 对象形式

configureWebpack: {
    // 修改entry配置
    entry: './src/main.js',
    // 修改output配置
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    resolve: {
        // 别名配置
        alias: {
            assets: "@/assets",
            common: "@/common",
            components: "@/components",
            // 建议改成如下方式
            '@assets': "@/assets",
            '@common': "@/common",
            '@components': "@/components",
        },
    },
},

configureWebpack 函数形式

configureWebpack: config => {
    if (process.env.NODE_ENV === 'production') {
        // 为生产环境修改配置...
        config.mode = 'production'
    } else {
        // 为生产环境修改配置...
        config.mode = 'development'
    }
    // 开发生产共同配置别名
    // 直接修改配置
    config.resolve.alias['@assets'] = resolve('src/assets'),
    //返回一个将要合并得对象
    return{
        resolve: {
            alias: {
                '@assets': resolve('src/assets'),
            },
        }
    }
},

tips:assets: "@/assets"写法 在<img src="assets/logo.png" alt="">中配置无效,具体原因可能是直接把assets当成了根路径,改为@assets: "@/assets"即可。前面必须添加一个符合@,简单测试了一下,好像必须是@开头,类似$assets写法,也不生效。

示例:

<!-- assets写法,在src中,不生效 -->
<img src="assets/logo.png" alt="">
<!-- 生效 -->
<img src="@assets/logo.png" alt="">
<home></home>
<script>
// 以下2种写法都生效
import home from "components/index.vue";
import home1 from "@components/index.vue";
</script>
  • chainWebpack:

是一个函数,会接收一个基于 webpack-chainChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。

Vue CLI 内部的 webpack 配置是通过 webpack-chain 维护的。这个库提供了一个 webpack 原始配置的上层抽象,使其可以定义具名的 loader 规则和具名插件。

你可以在vue.config.js文件中使用chainWebpack来添加、修改或删除webpack配置。它提供了一种更灵活的方式来修改webpack配置,可以在配置过程中进行更细粒度的控制。

例如,你可以使用chainWebpack来添加一个新的loader或plugin。

例子:

chainWebpack: (config) => {
    config.resolve.alias
        .set("@", resolve("src"))
        .set("@static", resolve("public/static"))
    // 修改Loader选项
    config.module
        .rule('vue')
        .use('vue-loader')
        .tap(options => {
            // 修改他的选项
            return options
        })
    // 添加一个新的loader
    config.module
        .rule('custom-loader')
        .test(/\.custom$/)
        .use('custom-loader')
        .loader('custom-loader')
        .end();
    // 替换一个规则里的Loader
    const svgRule = config.module.rule('svg')
    // 清除已有的loader。
    // 如果你不这样做,接下来的loader会附加在该规则现有的 loader 之后。
    svgRule.uses.clear()
    // 添加要替换的 loader 
    svgRule
        .use('vue-svg-loader')
        .loader('vue-svg-loader')
        .end();
}

参数说明:

name 是 webpack-chain 里的key,就是要加入的插件在 webpack-chain 配置里的 key ,就是我们自定义插件的名字,一般我们都保持跟插件名称相同。

WebpackPlugin 使用的 webpack 插件名,在这里,可以直接使用插件,无需进行实例化,就是不需要 new WebpackPlugin()

args 插件的参数信息。特别注意,args是一个数组,例如 [{},{}] 这种方式,可以配置多个插件实例。

tips:需要注意的是,这两个选项可以单独使用,也可以同时使用。如果同时使用,configureWebpack 的配置会被合并到 chainWebpack 的配置中。

无论是使用 chainWebpack 还是 configureWebpack ,都需要在vue.config.js文件中进行配置,并且需要重新启动开发服务器或重新构建项目才能使配置生效。

webpack中的url-loader和file-loader的区别

webpack对png等图片静态资源打包用到的插件,对图片路径的处理方法常用的有两种,一种是file-loader,一种是url-loader

简单点说url-loader包含了file-loader,通过限定一个图片的大小(limit),来判断是否采用编码的方式。小于limit的时候使用base64进行压缩,大于则使用file-loader变成路径。

  1. file-loader

file-loader将图片移动到dist目录(或者outputPath定义的目录)下并返回一个相对于dist的路径

rules: [
    {
        test: /\.(png|jpg|gif)$/,
        use: {
            loader: 'file-loader',
            options: {
                name: '[name]_[hash:6].[ext]',
                outputPath: 'images/',
            }
        }
    }
]

效果:

<img src="http://localhost:8080/asset/img/logo.png"
  1. url-loader

url-loader包含了file-loader,但 url-loader 不依赖于 file-loader,相比file-loader多了一个limit配置项(1024 = 1kb),在超过limit的时候执行和file-loader相同的功能,当小于limit时会将文件打包成base64文件到js打包文件里,通过限定大小(limit),来判断是否采用编码的方式

rules: [
    {
        test: /\.(png|jpg|gif)$/,
        use: {
            loader: 'url-loader',
            options: {
                name: '[name]_[hash:6].[ext]',
                outputPath: 'images/',
                // url-loader的limit配置项
                //   40kb 以下的文件采用 url-loader
                limit: 1024*40
            }
        }
    }
]

效果:

<img src="data:image/png;base64,...."

url-loader会将图片转成base64文件放在打包js文件里,节约了一次HTTP请求,如果图片太大会导致加载慢(适合小图片)

最好两个不要放在一起,打包后可能产生未知问题。

loadURL 和 loadFile 的区别
这两者最大的区别是 loadURL 可以加载线上的资源地址而 loadFile 不能,两者都能加载本地的文件地址。

{
    appId: "lethe.com",
    productName: "my-project", // 项目名,也是生成的安装文件名,即wyDemo.exe
    copyright: "lethe Copyright © 2022", // 版权信息
    files: ["./main.js", "./dist"]
    extraFiles: [
      // 把指定的资源复制到程序根目录,即把server文件夹的内容复制到程序根目录,这里server文件夹下的内容相当于我的后台,我在background.js中有相应的处理。
      "./server",
    ],
    directories: {
      output: "dists", // 输出文件路径
    },
    win: {
      // win相关配置
      // icon: "./favicon.ico", // 图标,当前图标在根目录下,注意这里有两个坑
      requestedExecutionLevel: "requireAdministrator", //获取管理员权限
      target: ["nsis", "zip"], // 利用nsis制作安装程序
    },
    nsis: {
      oneClick: false, // 是否一键安装
      allowElevation: true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
      allowToChangeInstallationDirectory: true, // 允许修改安装目录
      // installerIcon: "./favicon.ico", // 安装图标
      // uninstallerIcon: "./favicon.ico", // 卸载图标
      // installerHeaderIcon: "./favicon.ico", // 安装时头部图标
      createDesktopShortcut: true, // 创建桌面图标
      createStartMenuShortcut: true, // 创建开始菜单图标
      shortcutName: "leDom", // 图标名称(项目名称)
    },
}

文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录