webpack4

70 阅读6分钟

安装webpack

首先初始化一下项目

npm init

webpackwebp-cli模块安装并保存到package.jsondevDependencies中,主要在开发环境中的依赖包

npm install webpack webpack-cli -save-dev

以上命令可以简写为

npm i webpack webpack-cli -D

安装好之后可以通过webpack -v查看版本号

基础配置

在项目中构建一个webpack.config.js,如下为webpack的正常配置

module.exports = {
    entry: '',               // 入口文件
    output: {},              // 出口文件
    module: {},              // 模块处理
    plugins: [],             // 插件
    devServer: {},           // 开发服务器配置
    mode: 'development'                 // 模式配置(默认是'production'生产环境)
}

实现一下webpack的简单配置

const path = require('path');

module.exports = {
    // 入口文件
    entry: './src/index.js',   
    output: {
        // 打包后的目录,必须是绝对路径
        path: path.resolve('dist'),
        // 打包后的文件名称
        filename: 'bundle.js'  
    }
}

配置执行文件

玩过vue的小伙伴都知道,在package.json中写入devbuild命令,分别使用npm run devnpm run build命令就可以进入开发环境或生产环境。

多入口配置

多入口文件有两种实现方法

  • 一种是写成一个数组,打包到一个文件中
  • 另一种是写成对象的形式,每个入口文件单独打包成对应的出口文件
const path = require('path')
module.exports = {
    // 数组形式
    // entry: ['./src/index.js','./src/login.js']
    
    // 对象形式
    entry: {
        index:'./src/index.js',
        login:'./src/login.js'
    }
    output: {
        // 使用[name].js,即出口文件名与入口文件名相同
        filename: '[name].js',
        path: path.resolve('dist')
    },
    module: {},
    plugins: [],
    devServer: {},
    mode: 'development'
}

css打包

Webpack在生产环境中有一个重要的作用就是减少http的请求数,就是把多个文件打包到一个js里,这样请求数就可以减少好多。在学习CSS打包之前,需要先对webpack.config.js里的Loaders配置项进行了解。

Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以的脚本和工具,从而对不同的文件格式进行特定处理。 简单的举几个Loaders使用例子:

  • 可以把LESS文件的写法转换成CSS,而不在使用其他转换工具。
  • 可以把ES6的代码,转换成大多浏览器兼容的JS代码。
  • 可以把React中的JSX转换成JavaScript代码。

注意:所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。

下面我们对Loaders的配置型简单梳理一下。

  • test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
  • use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)。

新建一个style.css文件 style.css写入一段样式代码

    body{
        background-color: red; 
        font-size:50px;
    }

CSS文件建立好后,需要引入到入口文件中,才可以打包得到。在src/index.js首行引入

import style from './css/style.css'

引入完成,我们就需要使用loader来解析CSS文件了,这里我们需要两个解析用的loader,分别是style-loadercss-loader

npm install style-loader css-loader -D

安装完成之后,配置loader

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: {
        index:'./src/index.js'
    },
    output: {
        path: path.resolve('dist'),
        filename: 'bundle.js'
    },
    module: {
        rules:[
            {
                // 正则,解析css文件
                test:/\.css$/,
                use:['style-loader','css-loader'],
                /*
                或者也可以这样写,方便配置参数
                use:[
                    {loader:'style-loader'},
                    {loader:'css-loader'}
                ]
                */
            }
        ]
    },
    plugins: [],
    devServer: {},
    mode: 'development'
}

拆分css

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            test: /\.css$/,
            use: ExtractTextWebpackPlugin.extract({
                // link方式不需要style-loader
                use: 'css-loader'
            })
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        // 打包位置在dist/css文件夹下
        new ExtractTextWebpackPlugin('css/style.css')

    ],
    devServer: {},
    mode: 'development'
}

这样就可以直接用link的方式引入进去

html打包

将html打包到dist目录,此时需要借助html-webpack-plugin插件

npm i html-webpack-plugin -D
const path = require('path')
// 在开头引入这个插件
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports = {
    entry: './src/index.js',
    output: {
        // 添加hash可以防止文件缓存,每次都会生成4位的hash串
        filename: 'bundle.[hash:4].js',
        path: path.resolve('dist')
    },
    module: {},
    plugins: [
        // 通过new一下这个类来使用插件
        new HtmlWebpackPlugin({
            // 用哪个html作为模板
            template:'./src/index.html',
            // 会在打包好的bundle.js后面加上hash串
            hash:true
        })
    ],
    devServer: {},
    mode: 'development'
}

打包后html自动引用js

如果开发中需要配置多个页面,html-webpack-plugin同样可以解决

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: {
        index:'./src/index.js',
        user:'./src/user.js'
    },
    output: {
        path: path.resolve('dist'),
        filename: '[name].js'
    },
    module: {},
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html',
            // 一一对应,index.js对应index.html
            chunks: ['index']
        }),
        new HtmlWebpackPlugin({
            template: './src/user.html',
            filename: 'user.html',
            chunks: ['user']
        }),

    ],
    devServer: {},
    mode: 'development'
}

引用图片

安装file-loaderurl-loade

npm i file-loader url-loader -D
  • file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。
  • url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

有的小伙伴会发现我们并没有在webpack.config.js中使用file-loader,但是依然打包成功了。我们需要了解file-loaderurl-loader的关系。url-loaderfile-loader是什么关系呢?简答地说,url-loader封装了file-loaderurl-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。 通过上面的介绍,我们可以看到,url-loader工作分两种情况:

  1. 文件大小小于limit参数,url-loader将会把文件转为DataURL(Base64格式);
  2. 文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。 也就是说,其实我们只安装一个url-loader就可以了。但是为了以后的操作方便,我们这里就顺便安装上file-loader。
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
                test: /\.css$/,
                use: ExtractTextWebpackPlugin.extract({
                    use: 'css-loader',
                    // 可以根据相对路径获取图片资源
                    publicPath:'../'
                })
            },
            {
                test: /\.(jpe?g|png|gif)$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        // 小于10k的图片自动转成base64格式
                        limit: 10240,
                        outputPath:'images/'
                    }
                }]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new ExtractTextWebpackPlugin('css/style.css')
    ],
    devServer: {},
    mode: 'development'
}

页面引用图片

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
                test: /\.css$/,
                use: ExtractTextWebpackPlugin.extract({
                    use: 'css-loader',
                    // 可以根据相对路径获取图片资源
                    publicPath:'../'
                })
            },
            {
                test: /\.(jpe?g|png|gif)$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        // 小于10k的图片自动转成base64格式
                        limit: 10240,
                        outputPath:'images/'
                    }
                }]
            },
            {
                test:/\.(html|html)$/,
                use:'html-withimg-loader'
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new ExtractTextWebpackPlugin('css/style.css')
    ],
    devServer: {},
    mode: 'development'
}

添加css3前缀