webpack4进阶配置
移动端CSS px自动转换成rem
需要两步来实现:
- px2rem-loader 在构建阶段将px转换成rem
- lib-flexible 页面渲染时动态计算根元素的font-size值(手机淘宝开源库)
下载插件并配置:
- npm i px2rem-loader lib-flexible
- module: {
- 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 glob
- const 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-plugin
- const 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-loadable
- index.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-plugin
- const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
- module.exports = {
- plugins: [
- new FriendlyErrorsWebpackPlugin(),
- ],
- };
webpack4进阶配置的更多相关文章
- github+hexo搭建自己的博客网站(六)进阶配置(搜索引擎收录,优化你的url)
详细的可以查看hexo博客的演示:https://saucxs.github.io/ 绑定了域名: http://www.chengxinsong.cn hexo+github博客网站源码(可以clo ...
- VSCode-python 进阶配置
VSCode-python 进阶配置 中文乱码 中文乱码,网上一堆解决方法,但是根本没有有效起作用的. 在python脚本的前面添加: # -*- coding:utf-8 -*- 并不能在控制台输出 ...
- Ubuntu Server下docker实战 02: docker进阶配置
在上一篇文章里<Ubuntu Server下docker实战 01: 安装docker>,我们已经把docker安装起来了,并运行了一个hello-world 这一篇,我们继续讲进阶配置. ...
- webpack4的配置你都掌握了么?
webpack5都出了,webpack4的的基本配置,解析ES6,引入CSS,编译Less,设置image等等,你都会了么? 解析ES6 了解Babel Babel是一个JavaScript编译器, ...
- webpack4.x配置详解,多页面,多入口,多出口,新特性新坑!!
花了差不多一天多的时间,重新撸了一遍webpack4.x的常用配置. 基本上常用的配置都熟悉了一遍,总体上来讲,为了对parcel进行反击,webpack从4.x开始,正在朝着尽可能的简化配置文件的方 ...
- webpack4入门配置
下面是抄过来的,方便自己翻越 webpack4.x入门配置 1.首先npm install webpack webpack-cli webpack-dev-server -g (mac电脑用超级管 ...
- webpack4基本配置
1.npm init 生成package.json文件 2.npm install webpack webpack-cil --save-dev 安装webpack和webpack-cli ...
- es6 装饰器decorator的使用 +webpack4.0配置
decorator 装饰器 许多面向对象都有decorator(装饰器)函数,比如python中也可以用decorator函数来强化代码,decorator相当于一个高阶函数,接收一个函数,返回一个被 ...
- Webpack4 splitChunks配置,代码分离逻辑
博客不知道啥时候写的了,一直在草稿箱没写完,突然感觉今年过去大半了,又没怎么写博客.写写完,有始有终 1.代码分离升级 原来项目代码分离是通过下面的配置,基于bundle-loader插件,通过rou ...
随机推荐
- 使用java代码动态配置与xml文件结合的方式使用mybatis-generator生成代码配置
1.使用java代码动态配置与xml文件结合的方式使用mybatis-generator生成代码配置 2.上代码:在resources目录下新建:generatorConfiguration.xml文 ...
- 关于N个小球放M个盒子解答
以下是关于关于N个小球放M个盒子的几种情况的解答,蛮详细的(来自博友的) 求精:关于N个小球放M个盒子解答 - chensmiles的日志 - 网易博客http://chensmiles.blog. ...
- 牛客网在线判题系统JavaScript(V8)使用
JavaScript作为一种弱类型的编程语言,语法和C/C++.JAVA等存在差别,但是对于大部算法题,不只是C/C++.JAVA,也依然可以使用JavaScript来实现.所以在牛客网中,如果你喜欢 ...
- 移动端自定义键盘的vue组件 ----keyboard
<style scoped lang="less"> .keyboard { /* height: 250px; */ width: 100%; position: f ...
- SpringBoot 03_利用FastJson返回Json数据
自上一节:SpringBoot 02_返回json数据,可以返回json数据之后,由于有些人习惯于不同的Json框架,比如fastjson,这里介绍一下如何在SpringBoot中集成fastjson ...
- 基础类型转化成String 转
基础类型转化成String 在程序中你可能时常会需要将别的类型转化成String,有时候可能是一些基础类型的值.在拼接字符串的时候,如果你有两个或者多个基础类型的值需要放到前面,你需要显式的将第一个值 ...
- appscan如何扫描移动应用APP
1.前置条件:让手机和电脑处于同一WIFI下 1打开appscan,选择手动探索/外部设备. 2在弹出的对话框页面点击右上角“记录代理配置”. 3在弹出的页面选择记录代理页签,设置Appscan代理端 ...
- 搞了一宿,弄完了一个POP3协议
POP3协议和SMTP协议都会了,加上PE文件的读写,APIHOOK,以及远程进程注入,我是不是就可以写个简单点的通过邮件传播的蠕虫病毒了,哈哈哈哈哈哈. 感觉POP3协议挺简单的,比那个该死的SMT ...
- Solr+HBase
- CF1140F - Extending Set of Points
题意:对于点集S,定义函数F(S)为对S不断扩展到不能扩展时S的点数.一次扩展定义为如果有一个平行于坐标轴的矩形的三个点在S中,则第四个点加入S. 动态在S中加点删点,每次操作完后求F(S)的值. 解 ...