webpack笔记(1)-基础用法

142 阅读4分钟

不进行配置,webpack默认打开webpack.config.js文件

 "scripts": {
    "build": "webpack"
  },

Loaders

webpack只支持js和json两种文件类型,其他的如html、css、less、jsx、vue的指令语法糖、字体等,webpack需要通过Loaders将原生这些不支持的类型转化成有效的模块,然后webpack解析的时候才能添加到依赖图中。

Loaders本身是一个函数,接收源文件作为参数,输出转换后的结果给下一步使用。

webpack一切皆js模块,所以需要各种loader转换成js。

module.exports = {
    // 放到module对象的rules数组中
    // test指定匹配规则,use指定使用的loader名称
    // use只有一个loader时是字符串,多个时是个数组
    module: {
        rules: [
            {test: /\.txt$/,use: 'raw-loader'}
        ]
    }
}

Plugins

用于增强webpack功能,用于打包输出文件的优化,资源管理和环境变量注入,作用于整个构建过程。
Loaders不能的,都可以使用Plugins完成,比如构建之前删除目录

image.png

module.exports = {
    // 放到plugins数组中
    plugins: [
        new HtmlWbpackPlugin({template: './src/index.html'})
    ]
}

Mode

用来指定当前的构建环境,有三个值:

image.png

资源解析-ES6/jsx

webpack支持js解析,但是并不是完全会解析ES6的语法特性,需要使用babel-loader进行解析,而该loader的使用需要在项目中配置.babelrc

  • plugins:一个plugin对应一个功能
  • preset:是一系列plugin的集合,解析es6的话,preset-env就可以了,解析react,使用preset-react
// .babelrc
{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ]
}

css/less等解析

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

css-loader是把css转化成commonJs,style-loader是把样式放到html的内联样式中,并不会生成单独的一个文件,需要使用MiniCssExtractPlugin插件把css提取成独立的文件。

文件/字体解析

可以用file-loader或者url-loader,url-loader可以将小图片自动转化成base64

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpeg|jpg|gif)$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        // 小于10k的图片自动转换
                        limit: 10240
                    }
                }]
            }
        ]
    }
}

image.png image.png 可见,图片打包进search文件了,只适用于js中引用,html和css中使用其他loader

文件监听

watch:需要刷新浏览器,文件进行I/O操作 WDS:配合HotMoudleReplacementPlugin插件使用,不刷新浏览器,不输出文件,而是将产物放到内存中读取。 WDM:webpack-dev-middleware,适用于定制化场景

 "scripts": {
     // --open参数含义:每次构建完成自动开启浏览器
    "dev": "webpack-dev-server --open"
  },
  // 在配置文件中
  plugins: [
      // 插件是webpack内置的,所以需要引入webpack
      // but,webpack.HotModuleReplacementPlugin 没有必要加,官网文档说配置了 hot: true 会自动引入这个 plugin。
      new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
      // 服务的基础目录
      contentBase: './dist',
      // 开启热更新
      hot: true
  }

WDS原理:待深入记录&理解

image.png

  • HMR Server 是服务端,用来将变化的 js 模块通过 websocket 的消息通知给浏览器端。
  • HMR Runtime是浏览器端,用于接受 HMR Server 传递的模块数据,浏览器端可以看到 .hot-update.json 的文件过来。
  • webpack 构建出来的 bundle.js 本身是不具备热更新的能力的,HotModuleReplacementPlugin 的作用就是将 HMR runtime 注入到 bundle.js,使得bundle.js可以和HMR server建立websocket的通信连接

webpack-dev-server和hot-module-replacement-plugin之间的关系?

  • webpack-dev-server(WDS)的功能提供 bundle server的能力,就是生成的 bundle.js 文件可以通过 localhost://xxx 的方式去访问,另外 WDS 也提供 livereload(浏览器的自动刷新)。
  • hot-module-replacement-plugin 的作用是提供 HMR 的 runtime,并且将 runtime 注入到 bundle.js 代码里面去。一旦磁盘里面的文件修改,那么 HMR server 会将有修改的 js module 信息发送给 HMR runtime,然后 HMR runtime 去局部更新页面的代码。因此这种方式可以不用刷新浏览器。
  • hot-module-replacement-plugin 包给 webpack-dev-server 提供了热更新的能力。

原理文档:zhuanlan.zhihu.com/p/30669007

文件指纹

用于版本控制,改变则不会从缓存中取。
不能和热更新同时使用,需要配置dev和prod两个不同的环境。

  • hash:和整个项目的构建有关,只要文件有修改,整个项目构建的hash也会跟随修改。
  • chunkHash:和webpack打包的chunk有关,不同的entry会生成不同的chunkhash值,一般js文件使用。
  • contentHash:根据文件内容改变而变化。一般用于css。 占位符含义:

image.png

'use strict';

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    entry: {
        index: './src/index.js',
        search: './src/search.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name]_[chunkhash:8].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /.js$/,
                use: 'babel-loader'
            },
            {
                test: /.css$/,
                use: [
                    // style-loader和MiniCssExtractPlugin是冲突的,所以使用MiniCssExtractPlugin.loader
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test: /.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]_[hash:8].[ext]'
                        }
                    }
                ]
            },
            {
                test: /.(woff|woff2|eot|ttf|otf)$/,
                use: {
                    loader: 'file-loader',
                    options: {
                        name: '[name]_[hash:8].[ext]'
                    }
                }
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name]_[contentHash:8].css'
        })
    ]
};

代码压缩

  • js文件可使用webpack内置的uglifyjs-webpack-plugin,个性化可以自行再配置
  • css使用c,需要配合预处理器cssnano使用, optimize-css-assets-webpack-plugin默认配置
  • html使用html-webpack-plugin
plugins: [
    new OptimizeCssAssetsWebpackPlugin({
        assetNameRegExp: /\.css$/g,
        // cssnano是属于默认配置,可以不写不安装
        cssProcessor: require('cssnano')
    }),
    new HtmlWebpackPlugin({
        // template:生成filename的文件模版,支持ejs等
        template: path.join(__dirname, 'src/search.html'),
        // 输出文件的文件名称
        filename: 'search.html',
        // 允许插入到模版的chunk,不配置则会把output中所有的chunk都插入
        chunks: ['search'],
        // 向template中注入所有的静态资源
        // 1、true或者body:所有JavaScript资源插入到body元素的底部 
        // 2、head: 所有JavaScript资源插入到head元素中 
        // 3、false: 所有静态资源css和JavaScript都不会注入到模板文件中
        inject: true,
        // 设置静态资源的压缩情况,html-minifier
        minify: {
            html5: true,
            collapseWhitespace: true,
            preserveLineBreaks: false,
            minifyCSS: true,
            minifyJS: true,
            removeComments: false
        }
    }),
    new HtmlWebpackPlugin({
        template: path.join(__dirname, 'src/index.html'),
        filename: 'index.html',
        chunks: ['index'],
        inject: true,
        minify: {
            html5: true,
            collapseWhitespace: true,
            preserveLineBreaks: false,
            minifyCSS: true,
            minifyJS: true,
            removeComments: false
        }
    })
]

极客时间-玩转webpack