likes
comments
collection
share

webpack 基础总结

作者站长头像
站长
· 阅读数 75

WHAT IT IS?

webpack 是一个 静态的、 模块化的 打包工具,为现代 JavaScript 应用提供服务。

为什么说是静态的、模块化的?

webpack 将各种模块和资源 最终打包为 一个或多个静态文件,之后可以部署到静态服务器上执行; webpack 支持多种模块化规范,包括 commonJs、ES6 module、AMD、UMD等。

webpack 是怎么打包的,什么是 webpack 依赖图?

webpack 首先找到入口文件, 之后从入口文件开始,递归查找分析模块之间的依赖关系,构建一个完整的依赖图, 最后遍历依赖图,打包一个个模块, 在打包过程中,对不同类型的文件需要使用对应的 loader 来处理, 另外,plugin 也贯穿了构建的整个过程。

loader 和 plugin 的区别是什么?

loader 用于将特定的模块类型进行转换; plugin 用于更加广泛的任务,如打包优化、资源管理、环境变量注入等。

HOW TO USE?

入口和出口的配置

使用 entry 和 output,例如, path 为 目录,默认是生成一个 dist 文件夹,这里改为 bundle, path 需要为一个绝对路径,所以采用 path.resolve 来拼接。

module.exports = { 
	entry: "./src/index.js",
  output: {
      filename: "main.js",
      path: path.resolve(__dirname, "./bundle"),
      clean: true,
  },
}

基本 loader 的使用

css / less / postcss

处理 css 文件,一般需要用到 css-loader 和 style-loader, 首先,使用 css-loader 来解析 css 文件,将其加入到构建依赖中,但是此时样式还不会生效; 之后,使用 style-loader,它是负责将 css 代码动态地注入到 HTML 页面中,从而使样式生效。 所以,配置如下:css-loader 写在后面,因为 从后向前 采用loader。

module.exports = { 
//...
rules: [
    {
        test: /\.css$/i,
        use: [
            "style-loader",
            "css-loader",
        ],
    },
  	//...
]
}

那 postcss 是啥? postcss 是一个用 js 工具和插件 转换 css 代码的工具,不同于上述的 loader 我们可以对该 loader 进行一些选项配置, 如选择一些插件,如给 css 添加浏览器前缀的 autoprefixer、预设配置 postcss-preset-env等。 可以直接在 webpack 中配置,也可以单独创建一个 postcss.config.js 文件来配置。 方法一、直接配置(较麻烦)

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                    {
                      // 其他选项
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

方法二、单独文件配置(好)

module.exports = {
  plugins: [
    [
      'postcss-preset-env',
      {
        // 其他选项
      },
    ],
  ],
};

资源模块 assetModule

webpack 有内置的资源模块 asset modules,可用于 字体、icons、图片等资源的处理。 asset modules 有 4 中模块类型:

asset / resource : 导出为一个单独的文件并导出 URL; asset / inline : 导出一个资源的 data URI,采用 base 64 编码并直接嵌入到文档中; asset / source: 导出资源的源代码; asset: 自动在 resource 和 inline 中选择,根据资源的大小 limit;

最常用的是前两种,asset综合了前两种, 可以自行设定 limit, 例如为 60kb, 对于小于 60kb 的图片,采用asset/inline; 对于大于 60kb 的图片,采用asset/resource;

module.exports = { 
  module: {
     rules: [
       {
         test: /\.png/,
         type: 'asset/resource'
       }
     ]
   },
}

两种方式有什么区别?asset/inline VS resource? 对于较小的文件,适合采用 asset/inline ,因为这样可以减少文件数目,进而减少 http 请求次数; 而对于较大的文件,如果还采用 asset/inline 的话, 会使打包出来的文件过大,增加加载时间;

img/png/jep/jepg/gif/svg 等

图片资源为 asset modules, 无需另外安装 loader 即可打包,思考以下两个问题: 到底 inline 还是 resource? 设置一个 maxSize,低于这个大小的图片采用 inline。 另外,如何控制打包出来的文件的文件名? 可以使用 generotor:

[name]:原文件名 [hash:8]: 长度为 8 的随机hash值 [ext]:原后缀

module.exports = { 
  module: {
     rules: [
        {
            test: /\.(jpe?g|png|gif)$/,
            type: "asset",
            generator: {
                filename: "[name]_[hash:8][ext]",
            },
            parser: {
                dataUrlCondition: {
                    maxSize: 20 * 1024, // 20kb
                },
            },
        },
     ]
   },
}

js 使用babel

将 js 文件中的 ES6+ 代码转换为向前兼容的代码, babel 和 postcss 一样,需要额外配置插件,如转换箭头函数、转换const、let等, 可以单独使用某个插件如 "@babel/plugin-transform-arrow-functions", 也可以直接使用 babel 预设的配置 "@babel/preset-env"。同样,可以直接在webpack.config中配置,也可以单独创建一个配置文件。 方法一、直接配置

module.exports = { 
  module: {
     rules: [
        {
            test: /\.js$/i,
            use: [
                {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-env"],
                    },
                },
            ],
        },
     ]
   },
}

方法二、单独设置 babel.config.js

module.exports = {
    presets: ["@babel/preset-env"],
};

vue/ts

基本 plugin 的使用

clean

每次打包前将之前的文件清除

html-webpack-plugin

打包时会自动生成一个 html 文件,自动帮我们引用生成的 main.js 文件。 可以传入 title 参数,改变文档的标题; template 参数,用于手动选择模板文件,如 vue2 中需要生成一个 id 为 app 的 div 元素。

    plugins: [
        new HtmlWebpackPlugin({
            title: "nohao,webpack",
            template: "./index.html",
        }),
    ],

define-plugin

DefinePlugin 是 webpack 内置的插件,用于创建全局变量, 注意当 value 为字符串时,会将其作为 js 代码执行,所以需要用两层引号或者JSON.stringify()

new DefinePlugin({
    BASE_URL: JSON.stringify("./"),
    // BASE_URL: "'./'",
}),

自带的全局变量有:process.env.NODE_ENV, 当为开发环境是,值为 development;当为生产环境是,值为 production.

resolve 资源解析

文件路径解析

常常遇到 import 的文件路径不带后缀,此时需要根据 extensions 列表查找是否有这些类型的文件。

module.exports = {
  //...
  resolve: {
    extensions: ['.js', '.json', '.wasm'],
  },
};

或者有时候文件路径为一个文件夹,需要根据 mainFiles 查找对应文件。

module.exports = {
  //...
  resolve: {
    mainFiles: ['index'],
  },
};

dev-server 使用

加快开发速度,可以使用webpack建立一个开发服务器, 使用dev-server,会将打包的代码存在内存中,而不是磁盘中,所以速度更快,

devServer 的配置:

hot:true,默认为true,表示开启热模块更新; open:true,默认为false,为true时自动打开浏览器; compress:true,默认为fasle,为静态文件开启 gzip compression; host: XXXX,设置主机地址,一般设置为 localhost 或者 127.0.0.1,也可以设置为 0.0.0.0,

热模块替换HMS

模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除模块,而无需重新加载整个页面。 例如在 main.js 中引入了一个模块 greeting.js, greeting.js 的内容为:

console.log("nihao");
// console.log("哦嗨哟");

没有配置好时,我们把第二行取消注释,页面会整个刷新, 但是开启HMS之后,同时在 main.js 中设置需要热更新的模块(accept):

import "./utils/greeting";
if (module.hot) {
    module.hot.accept(["./utils/greeting", "./utils/add"], () => {
        console.log("greeting module 热更新啦");
    });
}

这下我们仅仅改变 greeting.js,页面就只会部分更新啦。

题外话:回环地址和0.0.0.0

127.0.0.1 是一个回环地址,当本机向 127.0.0.1 请求时,会在计算机内部路由回自身,直接通信。

0.0.0.0 ,当服务器将 host 设置为 0.0.0.0 时,服务器会监听本机所有网卡的IP地址,因此只要是和本机处于一个局域网的主机就可以通过 本机的ip地址 和 端口号 访问到网站。 举例:我在电脑上打开了一个devServer,设置为0.0.0.0:8888,电脑的ip地址为x1.x2.x3.x4, 那么我在手机浏览器上输入:http://x1.x2.x3.x4:8888 ,nice!访问到页面了!

转载自:https://juejin.cn/post/7283797053338615849
评论
请登录