webpack 简单入门介绍

443 阅读5分钟

webpack简单使用

官网给出的的解释:本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

webpack是基于nodejs的,所以语法遵循commonJs模块化规则

一个简单webpack配置通常包括以下几种属性:

momdule.exports = {
    mode: '',
    entry: {},
    output: {},
    devtool: '',
    module: {},
    plugins:{},
    devServer: {},
    resolve: {},
    optimization: {}
}

下面是一些简单常用的配置属性:

entry

用来配置webpack打包的入口文件,webpack会根据entry指定的文件,查找依赖文件,进行打包,可以配置单入口或者多入口。

单入口配置:
const path = require('path');
module.exports = {
    entry: path.resolve(__dirname, '../src/index.js')
}

默认entry会打包src下面的index.js文件,打包到dist文件夹生成一个main.js

上面代码用到一个node中自带的变量__dirname,是指当前文件所在的文件夹的绝对路径。

这里默认配置文件和入口主文件在项目中的位置:

image.png

假如该配置文件的路径是在/Users/chensir/project/myapp/config/webpack.config.js

那么__dirname输出的就是:

 /Users/chensir/project/myapp/config

另外还有一个变量 __filename,是指当前文件所在的绝对路径,输出的是:

/Users/chensir/project/myapp/config/webpack.config.js

可以使用字符串直接拼接成一个完整的路径,去在webpack配置中使用,例如:

const file = __dirname + "/index.html"

如果需要的文件或者文件路径在该文件的外层,需要使用node中自带的核心模块==path==,作用是拼装转换路径生成一个绝对路径:

const path = require('path');
let filePath = path.resolve(__dirname, '../src/index.js')

filePath输出的就是: /Users/chensir/project/myapp/src/index.js


output

出口配置

output属性可以配置webpack打包之后,输出的文件目录以及文件的名称。默认情况,配置文件和src文件夹位置同级,主入口文件经过打包之后,会默认出入到./dist/main.js,其他文件默认输入到./dist文件夹下。

这里默认配置文件和入口主文件在项目中的位置:

image.png

简单的一个出口配置:

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

output 属性告诉 webpack 在哪里输出它所打包后的文件,以及如何命名这些文件。

常见的output配置:

module.exports = {
    entry: path.resolve(__dirname, '../src/index.js')
    output: {
        path: path.resolve(__dirname, '..', 'dist'),
        filename: 'js/[name].[hash:8].js',
        chunkfilename: 
        publicPath:
        clean: true    // webpack 5.20.0+版本支持,不需要在使用clean-webpack-plugin
        
    }
}

主要参数:

  • path: 打包后的js文件输出到哪里,一个绝对路径。只影响js文件的位置,css和图,在他们各自的配置中
  • filename: 打包后的文件名称,可以写额外的文件夹地址: 'static/js/[name].js'
  • chunkFilename: 非主入口文件打包后的文件名称,例如:import() 异步导入的文件
  • publicPath: 加载静态资源时的前缀

==一般配置路径相关参数时,publicPath以/结尾,loader中配置path和filename涉及路径时,不用以/开头==

还有两个比较重要的配置: library、libraryTarget,新版webpack将要弃用libraryTarget,改为在library.type配置:

  • library: 用来设置主入口导出赋值给什么变量
  • libraryTarget: 设置以什么方式导出

entry和output共同配置多入口文件:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

let mainname = 'my-main'
module.exports = {
    entry: {
        index: path.resolve(__dirname, '../src/index.js'),
        home: path.resolve(__dirname, '../src/home.js'),
        [mainname]: path.resolve(__dirname, '../src/main.js')
    },
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: 'static/js/[name].js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: __dirname + "/index.html",
            filename: 'index.html',
            chunks: ['index']
        }),
        new HtmlWebpackPlugin({
            template: __dirname + "/index.html",
            filename: 'home.html',
            chunks: ['home', 'my-main']
        })
    ]
}

entry中可以使用[]去使用变量当做名字。配置output的filename时,可以使用占位符[name],会直接使用entry中配置的入口文件的名字,还有其他的占位符,如: [hash:8] [ext]。


module

webpack只会识别符合规范的普通js文件、json文件,像es6新语法, jsx、vue,css,图片等文件,都需要使用特殊的loader,去解析转换。在module模块中配置rules,webpack会根据规则,当识别特定的文件时,交给对应的loader去解析。

loader实际就是一个函数,会引入文件在内部进行解析转化后输出

module.exports = (file) => {
    .....
    return xxxxx
}

一个简单的loader使用:

const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};

当碰到==在 require()/import 语句中被解析为 '.txt' 的路径时==,在打包之前,webpack会先使用raw-loader 转换一下。

在webpack配置中loader两个属性

  1. test属性,匹配哪些文件需要使用loader转换
  2. use属性,匹配到的文件使用那种loader准换。可以直接传入loader名称,如果loader需要一些配置,像babel-loader,可以传入一个对象。如果需要使用多个loader,需要传递一个数组。注意:==当多个loader时,是从数组的最后一个loader以此向前解析。==

常见的需要loader处理的文件:

css、scss、less等处理样式的文件:

在webpack中,直接使用import 或者 requore引入css文件是不支持的,需要使用css-loader去处理css文件,css-loader会将css文件引入,解析转换文件还需要其他的loader和插件处理。

在webpack中引入的css文件或者(scss、less,还需要其他loader)等css预处理文件,最终可以生产两种格式。

  1. 最直接的转成style标签插入到html中,将css文件中的样式写入style标签中,最后插入的html中
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    }
}

需要先使用css-loader识别引入css文件,在利用style-loader将生成的style标签插入到html中。

使用style标签插入的方式,配置起来是简单的,但是一个完整的项目,会有众多css文件,将全部的css文件一下插入页面中,加载是会阻塞js的执行,这样页面加载时间会很长,所以还有另外的一种方式:

  1. 把css文件生成单独的css文件,使用link引入

需要安装mini-css-extract-plugin插件,这个插件会提供一个loader,并且需要配置插件

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            name: 'css/[name].[ext]',
            chunkFilename: "css/[id].css"
        })
    ]
}

MiniCssExtractPlugin解析后,会将所有的文件生成一个css文件,后面优化会处理拆分css文件

scss、和less这些css预处理器文件,还需要对应的loader去处理

scss 需要使用sass-loader,less需要使用less-loader。还需要配置一些指定的options。例如配置source map

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'less-loader',
            options: {
              sourceMap: true,
            },
          },
        ],
      },
    ],
  },
};

js jsx ts tsx文件:

webpack打包时,只能识别符合规范的es5语法,如果要解析转换es6语法,需要用到一些特定的loader去处理。

简单的处理js文件的loader的配置:

module.export = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            '@babel/preset-react',
                            '@babel/preset-env'
                        ],
                        plugins: []
                    }
                }
            }
        ]
    }
}

bable用于代码的转译,将打包之前的代码转换成符合预期规范的代码。在转译的 过程中,babel 内部经历了「==解析 - 转换 - 生成==」三个步骤

babel-loader负责将js、ts等文件引入。@babel/core是babel的核心模块,内部有对代码进行转换的核心方法,至于转换成什么需要用到==preset==(预设)和==plugin==(插件)来处理。可以直接配置在webpack中,也可以单独创建一个++++++babel++++.config.js++文件配置,在babel解析转换时,会按照本地的配置来。

babel是基于插件化的,想一些特定的语法需要特定的babel插件里,如果不配置,那输入和输出就是一样的,无法解析

常见的preset

  • @babel/preset-env
  • @babel/preset-react
  • @babel.preset-typescript

babel参考文章:www.cnblogs.com/bai1218/p/1…

ts、tsx文件想要校验还需其他配置:

babel提供了处理ts文件的预设,@babel/preset-typescript。 还需要安装typescript,去初始化一个ts.config.js,校验ts类型文件,并且提供提示,一些依赖提示需要安装官方提供的ts类型文件,如react需要安装@types/react,这样才能检验和提示功能。

png jpg svg 以及woff字体图标文件:

像图片之类的文件,需要使用url-loader和file-loader处理:

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: [
                  {
                    loader: 'url-loader',
                    options: {
                      name: 'static/images/[name].[hash:8].[ext]',
                      limit: 10 * 1024
                    }
                  }
                ]
            }
        ]
    }
}

图片较小时,可以使用url-loader处理成base64格式直接引入,减少页面的http请求,同时对于较大的图片,可以设置limit,如果大于限制,file-loader会处理成单独的图片文件,打包到指定文件夹。

在 webpack5 中,asset modules 替换了上述的 loader,添加了 4 中内置类型:

  • asset/resource 之前由 file-loader 实现
  • asset/inline 之前由 url-loader 实现
  • asset/source 导出资源的源码(字符串类型),之前由 raw-loader 实现
  • asset 可以自动选择导出为 data URI 还是直接发送文件,之前由 url-loader 实现。