webpack4进阶配置
移动端CSS px自动转换成rem
需要两步来实现:
- px2rem-loader 在构建阶段将px转换成rem
- lib-flexible 页面渲染时动态计算根元素的font-size值(手机淘宝开源库)
下载插件并配置:
npm i px2rem-loader lib-flexiblemodule: {rules: [{test: /\.less$/,use: [MiniCssExtractPlugin.loader, "css-loader",{loader: "postcss-loader",...},{loader: "px2rem-loader",options: {remUnit: 75,remPrecision: 8}},"less-loader",]},]
},
然后,需要将淘宝的插件的内联在html文件中:
<script src='../node_modules/lib-flexible/flexible.js'></script>
静态资源内联
静态资源内联是指将CSS、JS等静态文件中的内容抽离出来,内联到html中。我们之前借助插件做到了将内联的资源独立成文件,为什么还要将资源内联呢?
资源内联的意义:
- 代码层面:
- 页面框架的初始化脚本(这些脚本往往需要在第一时间加载,多将其写在<head>中)
- 上报相关打点
- CSS内联避免页面闪动
- HTML可以动态地将不同的meta标签内联进来
- 请求层面:
- 减少http请求
HTML和JS内联
使用raw-loader,注意要使用0.5的版本,新版本的存在一些问题。
npm i raw-loader@0.5.1/src/meta.html 【例:腾讯NOW直播官网的meta标签】
<meta charset="UTF-8">
<meta name="viewport" content="viewport-fit=cover,width=device-width,initial-scale=1,user-scalable=no">
<meta name="format-detection" content="telephone=no">
<meta name="keywords" content="now,now直播,直播,腾讯直播,QQ直播,美女直播,附近直播,才艺直播,小视频,个人直播,美女视频,在线直播,手机直播">
<meta name="name" itemprop="name" content="NOW直播—腾讯旗下全民视频社交直播平台">
<meta name="description" itemprop="description" content="NOW直播,腾讯旗下全民高清视频直播平台,汇集中外大咖,最in网红,草根偶像,明星艺人,校花,小鲜肉,逗逼段子手,各类美食、音乐、旅游、时尚、健身达人与你24小时不间断互动直播,各种奇葩刺激的直播玩法,让你跃跃欲试,你会发现,原来人人都可以当主播赚钱!">
<meta name="image" itemprop="image" content="https://pub.idqqimg.com/pc/misc/files/20170831/60b60446e34b40b98fa26afcc62a5f74.jpg">
<meta name="baidu-site-verification" content="G4ovcyX25V">
<meta name="apple-mobile-web-app-capable" content="no">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">/node_modules/lib-flexible/flexible.js 【npm下载的淘宝库】/src/index.html
<!DOCTYPE html>
<html lang="en">
<head>${ require('raw-loader!./meta/meta.html') }<title>Hello Webpack</title><script>${ require('raw-loader!babel-loader!../node_modules/lib-flexible/flexible.js') }</script> <!-- 先用raw-loader内联,再用babel-laoder转换语法 -->
</head>
<body>
<div id="root"></div>
</body>
</html>
CSS内联
借助style-loader即可
{loader: 'style-loader',options: {insertAt: 'top', // 样式插入到<head>singleton: true, // 将所有style标签合并成一个}
}
多页面应用打包方案
每当增加一个页面,我们就手动地在webapck配置中对应增加一个entry、html-webpack-plugin。
一定可以有更优的方案,那就是:动态获取entry的数量、然后自动生成html-webpack-plugin。
需要借助glob.sync,可以在每次构建的时候获取页面的数量。这需要我们规范目录,将每个页面(文件夹)都放在src文件夹下,每个页面(文件夹)入口文件是index.js,入口页面是index.html。
npm i globconst glob = require('glob');const setMPA = () => {let entry = {};let htmlWebpackPlugins = []; const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js')); // 获取所有页面的入口文件路径。entryFiles是所有页面index.js的绝对路径形成的数组entryFiles.forEach((file)=>{let name = file.match(/src\/(.*)\/index\.js/);let pageName = name && name[1];entry[pageName] = file;htmlWebpackPlugins.push(new HtmlWebpackPlugin({template: file.replace("index.js","index.html"),filename: `${pageName}.html`,chunks: [`${pageName}`],inject: true,minify: {html5: true,collapseWhitespace: true,preserveLineBreaks: false,minifyCSS: true,minifyJS: true,removeComments: true,},}))});return {entry,htmlWebpackPlugins}
};const result = setMPA();module.exports = {entry: result.entry,output: {filename: "bundle[chunkhash:8].js",path: path.join(__dirname, "/dist")},mode: 'production',module: {rules: [...]},plugins: [...result.htmlWebpackPlugins, // 将N个HtmlWebpackPlugin对象插入列表new MiniCssExtractPlugin({filename: '[name][contenthash:8].css'}),new OptimizeCssAssetsPlugin({assetNameRegExp: /\.css$/g,cssProcessor: require('cssnano'),}),new CleanWebpackPlugin(),
};
使用Source Map
什么是source map?顾名思义,就是代码地图,可以将构建前后的两份代码做一个映射。
sourcemap的作用:构建后的代码已经变了模样,没有可读性,开发调试的时候无法定位问题所在。sourcemap的存在可以直接将问题定位到源代码,排查问题。
配置文件中devtool属性可以设置,有非常多的类型可选,一般情况下,开发环境使用"source-map",生产环境关闭。
module.exports = {devtool: "source-map"
};
代码分割
对于大型的web应用来说,将所有的代码编译成一个文件显示不好,会造成文件体积过大以及需要加载大量与首屏无关的代码,用户体验不好。webpack提供将代码分割成chunk(语块),当代码运行到需要的它们的时候再进行加载。
代码分割有两种类型:
- 抽离公共资源。(比如基础库入React/Vue,React-Router/Vue-Router。或者自己编写的公共模块)
- JS懒加载,使得初始状态下的代码更小(首屏优化)
抽离公共资源
需要借助插件,有两个插件可供选择:html-webpack-externals-plugin 和 SplitChunsPlugin(webpack4内置,代替webpack3的CommonsChunkPlugin)
说明:
- 两个插件不要混用
- html-webpack-externals-plugin既可以将本地基础库分离,也可以直接使用CDN。本人试图将本地库进行分离,总是失败,暂没查明原因。
- 使用SplitChunksPlugin中chunks时,如果没有使用异步加载,chunks建议"all",但如果使用了异步加载,"all"则会导致错误,这时建议用"initial"
html-webpack-externals-plugin:
npm i html-webpack-externals-pluginconst HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');plugins: [new HtmlWebpackExternalsPlugin({externals: [{module: "react", // 代码中引入的库的名称entry: "https://11.url.cn/now/lib/16.2.0/react.min.js",// entry: "cjs/react", // 相对于node_modules/react的路径【官网示例,实际并不成功】global: "React", // 代码中引入的库的全局对象的名称},{module: "react-dom",entry: "https://11.url.cn/now/lib/16.2.0/react-dom.min.js",// entry: "dist/react-dom", // 相对于node_modules/react-dom的路径 【官网示例,实际并不成功】global: "ReactDOM",},],})
]
SplitChunksPlugin:
module.exports = {optimization: {splitChunks: {minSize: 0, // 分离包体积的最小大小cacheGroups: {commons: {// test: /(react|react-dom)/, // 通过正则匹配,只分离react/react-dom这两个库,不写test则不作限制name: 'commonss', // 分离块的名称,需要加在HtmlWebpackPlugin插件的chunks属性中,才能正确命名分离后的文件chunks: "all", // 需要分割哪些代码块,all表示所有代码块,async按需加载的代码块,initial初始化代码块// minChunks: 2, // 最小引用次数,少于这个引用次数就不会单独提取出来}}}}
};
JS懒加载
实现懒加载不需要对webpack配置,动态引入import('')语法还没有成为JS标准(也许不久的将来会),目前要借助js插件
实现懒加载:
- 如果使用的CommonJS,直接require.ensure即可
- 如果使用ES6模块化,需要借助第三方插件实现。(babel插件@babel/plugin-syntax-dynamic-import,且在.babelrc文件内配置)
npm i @babel/plugin-syntax-dynamic-import.babelrc
{"presets": ["@babel/preset-react","@babel/preset-env"],"plugins": ["@babel/plugin-syntax-dynamic-import", // 懒加载插件"@babel/plugin-proposal-class-properties"]
}
在此基础上,如果使用React开发项目,还可以使用react-loadable插件来更好的实现异步加载
npm i react-loadableindex.js中部分代码import Loadable from "react-loadable";
const TextLoad = Loadable({loader: () => import(/* webpackChunkName: 'text' */ './text'), // 通过注释的方式指定打包后的chunk的名字loading: ()=> <div>正在加载</div>
});class Search extends React.Component{constructor(props){super(props);this.state = {text: false,};}loadComponent = () => {this.setState({text: true})};render() {const { text } = this.state;return (<><div>你好,显示字体 Hello Webpacks</div>{text ? <TextLoad /> : null}<img alt="" src={logo} style={{ width: 100 }} onClick={this.loadComponent}/></>)}
}export default Search;
tree shaking(摇树优化)
一个文件会有多个方法、对象、语句,只要用到其中一小部分,便会将整个文件内的所有内容打包进去。tree shaking只把用到的方法打包进去,没用到的会在uglfiy阶段被擦出掉。
使用:webpack默认支持,生产环境默认开启
要求:必须是ES6的写法,CommonJS的方式不支持
Scope Hoisting
构建之后的代码存在大量闭包,导致:
- 文件体积增大
- 运行代码时创建的函数作用于变多,内存开销变大
scope hoisting就是减少闭包函数的声明。
原理:将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当地重命名一些变量以防止变量名冲突,以此减少闭包函数声明代码。
使用:webpack默认支持,生产环境默认开启
要求:必须是ES6写法,CommonJS的方式不支持
优化构件时命令行的显示日志
每次构建,命令行输出大量日志,有很多是我们完全不关心的,想要优化它,可以在webpack中设置state属性。
// 如果是打包,在最外层的state属性
module.exports = {stats: 'errors-only',
};
// 如果是devserver热更新
const devConfig = {devServer: {contentBase: './dist',hot: true,stats: 'errors-only', },
};
state的取值有:
- errors-only 只发生错误时输出
- minimal 只发生错误或有新的编译时输出
- none 没有输出
- normal 标准输出
- verbose 全部输出
我们希望是在发生错误的时候输出,当state为error-only时,如果没有错误,没有任何输出,不太友好。
借助插件:friendly-errors-webpack-plugin。此时将state设置成errors-only
npm i friendly-errors-webpack-pluginconst FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
module.exports = {plugins: [new FriendlyErrorsWebpackPlugin(),],
};
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1jot771valo8l
转载于:https://www.cnblogs.com/V587Chinese/p/11571515.html
webpack4进阶配置相关推荐
- PingingLab传世经典系列《CCNA完全配置宝典》-3.2 VLAN进阶配置
3.2 VLAN进阶配置 实验目的: 1.掌握跨交换机同VLAN的通信实现. 2.理解跨交换机同VLAN的通信原理. 实验拓扑: 实验步骤: 1.依据图中拓扑配置4台主机的IP地址,其中PC通过路由器 ...
- redirect路由配置 vue_Web前端:Vue路由进阶配置
大家好,我来了,本期为大家带来的前端开发知识是"Web前端:Vue路由进阶配置",有兴趣做前端的朋友,和我一起来看看吧! 1. 页面打开权限流程 页面是否能打开有以下两点判断: 1 ...
- webpack4.0配置记录(2)
接上一篇webpack4.0配置记录(1),继续记录学习webpack配置. 定义环境变量 new Webpack.DefinePlugin({//用来定义全局环境变量DEV:JSON.stringi ...
- PingingLab传世经典系列《CCNA完全配置宝典》-3.4 Trunk进阶配置
3.4 Trunk进阶配置 实验目的: 1.掌握Native vlan和Allow vlan的配置. 2.理解Native vlan和Allow vlan的功能. 实验拓扑: 实验步骤: 1.依据图中 ...
- Android Gradle进阶配置指南
简单的总结一下gradle: 1.Gradle是一种构建工具,它可以帮你管理项目中的差异,依赖,编译,打包,部署......你可以定义满足自己需要的构建逻辑,写入到build.gradle中供日后复用 ...
- Android Gradle进阶配置指南 1
简单的总结一下gradle: 1.Gradle是一种构建工具,它可以帮你管理项目中的差异,依赖,编译,打包,部署......你可以定义满足自己需要的构建逻辑,写入到build.gradle中供日后复用 ...
- 树莓派 + Home Assistant + HomeKit 从零开始打造个人智能家居系统 篇三:进阶配置 Home Assistant
树莓派 + Home Assistant + HomeKit 从零开始打造个人智能家居系统 篇三:进阶配置 Home Assistant 通过本篇教程,你将完成对 Home Assistant 的进一 ...
- github+hexo搭建自己的博客网站(六)进阶配置(搜索引擎收录,优化你的url,添加RSS)...
详细的可以查看hexo博客的演示:https://saucxs.github.io/ 绑定了域名: http://www.chengxinsong.cn hexo+github博客网站源码(可以clo ...
- 饥荒联机版linux服务器安装,饥荒联机版服务器怎么搭建?饥荒联机版服务器建立图文教程 六、进阶配置及启动-游侠网...
六.进阶配置及启动 配置管理员 cd ~/.klei/DoNotStarveTogether/MyDediServer/ vim adminlist.txt 然后写入用户id,这里不是指游戏ID,而是 ...
最新文章
- ORACLE SQL开发where子句之case-when
- 启明云端分享|SSW101B WIFI调试会遇到的问题答疑
- leetcode79. 单词搜索 网格地图搜索+回溯经典写法啦
- 利用STM32制作红外测温仪之硬件设计
- java7 nio2 新特性_JDK7新特性,你知道几个?
- Devexpress中Tdxnavbar的使用
- redhat-5.4故障排除
- 世界杯:为什么进攻大多沿着边路前进?
- (2)Spring框架----IOC基础快速入门
- vue改页面顶部浏览器标题栏图标、名称和地址栏详细教程
- Microsoft Office2010 安装包和安装方法
- 视频教程-思科CCNP专题系列②:EIGRP路由协议-思科认证
- 2022年版中国电子信息产业趋势预测及投资战略规划分析报告
- html图片边框的颜色,css图片的边框怎么设置颜色?
- Minecraft 1.12.2模组开发(五十五) 动画生物实体
- win10 休眠设置无效_win10怎么设置不休眠?win10休眠设置教程--系统之家
- AlertManager告警的单独使用及prometheus配置告警规则使用
- 高性能网站建设进阶指南:Web开发者性能优化最佳实践 pdf扫描版
- UTONMOS:元宇宙链游之风、燎原之势
- ACM入门及STL简介(转)
热门文章
- 联发科技嵌入式_英特尔联手联发科技重回移动5G征途,能否与高通抗衡?
- mysql include files_安装sphinx出现错误ERROR: cannot find MySQL include files.
- 请查收 | 2021 阿里妈妈技术文章回顾
- java反射成员变量_java反射之成员变量的反射
- python小白逆袭大神课程心得_python小白逆袭大神(深度学习7日训练营)——心得体会...
- oracle日志版本不同步,oracle11GR2 datagurad 配置后,敲入日志应用后查看归档日志序号不一致...
- 深度学习(12)TensorFlow高阶操作一: 合并与分割
- kafka重复消费问题
- Attention和增强RNN (Attention and Augmented Recurrent Neural Networks)
- (转)如何选择合适的射频模块