webpack的应用


Webpack就是将浏览器识别不了的文件转换为浏览器能识别的文件

webpack4的安装(以下全以webpack4版本进行,之后再用webpack5进行比较)

在安装webpack前要确保电脑已经安装了node.js

npm i webpack@4 -D -g是全局安装开发者模式的webpack其中-g代表全局安装-D代表开发者模式

npm i webpack-cli@3 -D -g是全局安装开发者模式的webpack-cli其中-g代表全局安装-D代表开发者模式

其他的安装与上同理

如果想局部安装就去掉-g即可。

全局运行webpack可以直接在命令行输入webpack就可进行打包

没有全局安装,但局部安装了。局部运行webpack需要在命令行输入npx webpack才能进行打包

webpack的配置文件

webpack.config.jswebpack的配置文件,当运行webpack会加载里面的配置

//webpack.config.js 模块化默认采用采用commonjs
//resolve用来拼接绝对路径的方法
const { resolve } = require('path')
module.exports = {
    //webpack配置
    //入口,webpack的打包起点文件
    entry: './src/index.js',
    //输出
    output: {
        //输出文件名
        filename: 'built.js',
        //输出路径
        //__dirname是node.js的变量,代表当前文件的目录绝对路径
        path: resolve(__dirname,'bulid')
    },
    //loader的配置
    module: {
    rules: [
    	//详细loader配置  不同文件必须配置不同loader处理
        {
            //text匹配哪些文件
            test: /\.css$/,//这里解析css资源
            //use使用哪些loader进行处理
            use: [
                //use数组中loader执行顺序:从右到左,从下到上依次执行
                //创建style标签,将js中的样式资源插入进行,添加到head中生效
                'style-loader',
                //将css文件变成common.js模块加载js中,里面内容是样式字符串
                'css-loader'
            ]
        }
      ]
	},
    //plugins的配置
    plugins: [],
    //模式
    mode: 'development'//开发模式
    //mode: 'production' 是生产模式,会对代码进行压缩
}

配置解析less文件的loader

在loader文件中如果使用的webpack是4的版本则下载的loader版本也需要旧版本

//webpack.config.js
module: {
    rules: [
        {
            test: /\.less$/,
            use: [
                'style-loader',
                'css-loader',
                //将less文件编译成css文件,然后依次编译为样式
                //打包前需要使用npm下载 less-loader和less
                'less-loader'
            ]
        }
      ]
	}
打包html资源

只需在plugins中配置 html-webpack-plugin即可,打包自动引入打包输出的所有资源

//webpack.config.js
const HtmlWebpackPlugin =require('html-webpack-plugin')//html-webpack-plugin需要通过npm下载
module.exports = {
    plugins: [
    new HtmlWebpackPlugin({
       		 //复制'./src/index.html'文件,并自动引入打包所有资源
    		template: './src/index.html' 	
    	})
	]
}
打包图片资源

loader中进行配置

要是报错大部分只需根据下载依赖包即可

//webpack.config.js
module: {
    rules: [
        {
            //这种处理方式只能处理index.js中引入的图片资源
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options:{
                //表示图片大小小于8kb,就会被base64处理
                limit: 8 * 1024
                //要是解析出现路径变为:[object Module],需要关闭es6模块化,使用commonjs解析
                esModule: false,
                //表示输出到根目录的imgs的文件夹中
                outputPath: 'imgs'
            }
        },
        {
            test: /\.html$/,
            //这是处理Html文件的img图片
            loader: 'html-loader'
        }
      ]
	}
打包其他资源

需要在loader中进行配置

和打包图片资源方法几乎一致

//webpack.config.js
module: {
    rules: [
        {
            //表示排除css/js/html资源
            exclude: /\.(css|js|html)$/,
            loader: 'file-loader',
            //表示输出到根目录的media的文件夹中
                outputPath: 'media'
        }
      ]
	}
devServer

可以实现自动化(自动编译已修改的文件,自动打开浏览器,自动刷新浏览器)

//webpack.config.js
//devServer启动指令 npx webpack-dev-server
const { resolve } = require('path')
module.exports = {
    devServer: {
        contentBase: resolve(__dirname, 'build'),
        //启动gzip压缩
        compress: true,
        //开启的端口号
        port: 3000,
        //自动打开默认浏览器
        open: true
    }
}
提取css为单独资源

用上方的方法打包css资源则会存在js文件中需要使用npm i mini-css-extract-plugin -D来进行安装,然后在webpack.config.js进行配置即可

//webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
    module:{
        rules: [
        {
            test: /\.css$/,
            use: [
                //用这个loader来代替style-loader
                MiniCssExtractPlugin.loader,
                'css-loader',
            ]
        }
      ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            //对输出的css文件进行重命名
            filename: './src/index.html'
        })
    ]
}
js语法检查eslint

语法检查用于检查语法错误和保证团队风格一致

这里使用airbnb来作为检查规则,需要安装npm i eslint-loader eslint-config-airbnb-base eslint-plugin-import -D

//webpack.config.js
module.exports = {
    module: {
        rules:[
            {
                //eslint只检查自己写的源代码
                test: /\.js$/,
                exclude: /node_modules/,//排除检查库
                loader: 'eslint-loader',
                options: {
                    fix: true //可以自动修复eslint错误
                }
            }
        ]
    }
}
eslint兼容性处理

为保证在任何浏览器都能运行需要对js做兼容性处理

需要安装npm i babel-loader @babel/core @babel/preset-env core-js -D

//webpack.config.js
module.exports = {
    module: {
        rules:[
            {
                //eslint只检查自己写的源代码
                test: /\.js$/,
                exclude: /node_modules/,//排除检查库
                loader: 'babel-loader',
                options: {
                    //预设:指示babel做怎么样的兼容性处理
                    presets:[
                        [
                            '@babel/preset-env',
                            {	//按需加载
                                useBuiltIns: 'usage',
                                corejs:{
                                    version:3//指定core-js把呢不能
                                },
                                targets: {//指定兼容性做到哪个版本浏览器
                                    chrome: '60,
                                    firefox: '60
,                               }
                            }
                        ]
                    ]
                }
            }
        ]
    }
}

webpack优化配置

HMR热模块替换

在开发环境中,一个模块发生变化,只会重新打包发生变化的模块

html文件和js文件默认不能使用 HMR,因为开发都是单页面应用,所以没必要开启html的热更新

//webpack.config.js
module.exports = {
    entry:['./src/js/index.js' ],
    devServer: {
        //开启HMR功能
        hot: true
    }
}
//index.js文件  这种方法不能处理入口文件
if(module.hot) {
    //一旦 module.hot 为 true, 说明开启了HMR功能
    module.hot.accept('./print.js',function(){
        //方法会监听 print.js 文件的变化,一旦发生变化,其他模块不会重新打包构建
        //会执行后面的回调函数
        print()
        //修改./print.js信息,只有该文件重新构建了
    })
}
source-map

提供源代码到构建后代码映射技术(如果构建后代码出错了,通过映射可以追踪源代码错误)

//webpack.config.js
module.exports = {
    devtool: 'source-map'//这样就开启了source-map
}

source-map的模式:

  • source-map:单独生成一个以.map为后缀的文件,发生错误能表明是哪个文件和源代码的错误位置
  • inline-source-map:直接在入口js文件中生成,发生错误能表明是哪个文件和源代码的错误位置
  • hidden-source-map:单独生成一个以.map为后缀的文件,发生错误显示原因,但没有源代码错误位置
  • eval-source-map:直接在入口js文件中生成,发生错误能表明是哪个文件和源代码的错误位置(为hash值)
  • nosources-source-map:单独生成一个以.map为后缀的文件,能找到错误信息,但是没有源代码信息
  • cheap-source-map:单独生成一个以.map为后缀的文件,能找到错误信息,但源代码错误信息只能精确到行
  • cheap-module-source-map:单独生成一个以.map为后缀的文件,能找到错误信息和源代码的错误位置
缓存

在生产环境中,对一个文件进行修改为了不需要所有文件都重新构建一次,就需要用到缓存

主要使用:

  • cacheDirectory: true
  • 文件名中添加contenthash
//webpack.config.js
module.exports = {
    output:{
        //这里增加contenthash值是因为保证重新构建文件发生改变,可以重新写入缓存
        //contenthash:根据文件的内容生成hash值。
        filename: 'js/built[contenthash:10].js'
    },
     //loader的配置
    module: {
    rules: [
    	{
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
                //开启babel缓存,第二次构建时,会读取之前的缓存
                cacheDirectory: true
            }
        }
      ]
	}
}
代码分割

通过code split可以更好的进行代码维护

//webpack.config.js
module.exports = {
    //可以将node_modules中代码单独打包成一个chunk
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
}

index.js入口文件中实现代码分割

//index.js文件
//import动态导入语法  能将某个文件单独打包 /* webpackChunkName: 'test' */代表打包后文件名为test
import(/* webpackChunkName: 'test' */'./test')//使用promise方法
.then(()=>{
    console.log('文件加载成功')
})
.catch(()=>{
    console.log('文件加载失败')
})
懒加载和预加载
//index.js文件
//放在按钮中当点击的时候才会加载test.js文件
document.getElementById('btn').onclick = function() {
    //正常加载可以认为是并行加载(同一时间加载多个文件)
    //webpackPrefetch: true表示启动预加载,预加载是指等其他资源加载完毕,浏览器空闲了再加载资源
    import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test')//使用promise方法
.then(()=>{
    console.log('文件加载成功')
})
.catch(()=>{
    console.log('文件加载失败')
})
}
dll

dll可以对第三窟进行单独打包,它的配置需要单独新建一个配置文件

运行打包需要使用webpack --config webpack.dll.js告诉webpack配置文件名变更了

//webpack.dll.js文件
//获取路径
const { resolve } = require('path')
//引入插件
const webpack = require('webpack')

module.exports = {
    entry: {
        //['jquery']表示要打包的库是jquery
        jquery: ['jquery']
    },
    output: {
        //最终打包生成的[name]是jquery
        filename: '[name].js',
        path: resolve(__dirname, 'dll'),
        library: '[name]_[hash]'//打包的库向外暴露的内容叫什么名字
    },
    plugins: [
        //打包生成一个manifest.json,提供和jquery映射关系
        new webpack.DllPlugin({
            name: '[name]_[hash]', //映射库的暴露内容名称
        	path: resolve(__dirname, 'dll/manifest.json') //输出文件路径
        })
    ]
}

同时需要在配置文件中告诉webpack哪些库不参与打包,并安装插件来让html自动引入资源npm i add-asset-html-webpack-plugin -D

//webpack.config.js文件
const { resolve } = require('path')
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exports = {
    plugins: [
        //告诉webpack哪些库不参与打包
        new webpack.DllReferencePlugin({
            manifest: re3solve(__dirname, 'dll/manifest.json')
        }),
        //让html自动引入资源
        new AddAssetHtmlWebpackPlugin({
            filepath: resolve(__dirname, 'dll/jquery.js')
        })
    ]
}
解决跨域问题
//webpack.config.js文件

module.exports = {
    devServer: {
        //使用服务器代理来解决开发环境的跨域问题
        proxy: {
            //一旦devServer服务器接收到 /api/xxx 的请求,就会把请求转发到另一个服务器
            '/api' : {
                target: 'http://localhost:3000'
            }
        }
    }
}
解决缓存失效问题

在原先的方法中,因为新增加hash值,其他文件修改会导致hash值变更也会修改主要入口文件index.js中的数据,导致重新打包后入口文件也会进行打包,这时就需要runtimeChunk配置来解决这个问题

//webpack.config.js文件

module.exports = {
    optimization: {
        //将当前模块的记录其他模块的hash单独打包成一个文件 runtime
        runtimeChunk: {
            name: entrypoint => `runtime-${entrypoint.name}`
        }
    }
}

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