webpack4进阶知识点(一)

1.移动端px自动转rem

下载px2rem-loader

npm i  px2rem-loader -D

页面渲染时计算根元素的font-size使用手机淘宝的lib-flexible

npm i  lib-flexible -S

并将其内联在网页内(raw-loader下节会讲解)


    

webpack.config.js

module.exports = {
    module: {
        rules: [{
                test: /\.css$/,
                use: [
                    MinicssExtractPlugin.loader, //此处用MinicssExtractPlugin.loader替代'style-loader'
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: [require('autoprefixer')]
                        }
                    },
                    {
                        loader:'px2rem-loader',
                        options:{
                            remUnit:75,
                            remPrecision:8
                        }
                    }
                ]
            },
        ]
    }
}

2.静态资源内联—raw-loader

css,js,图片等静态资源内联到html内,css内联避免页面闪动
下载raw-loader(raw-loader返回的是一个字符串)

npm i [email protected] -D

内联js:
html页面(raw-loader!babel-loader!后面是js文件路径)


    

内联css:

方案一:借助style-loader

webpack.config.js

module.exports = {
    module: {
        rules: [{
                test: /\.css$/,
                use: [
                    {
                        loader:'css-loader',
                        options:{
                            insertAt:'top',//——>样式插入到head
                            singleton:true //——>将所有的style标签合并成一个
                        }
                    },
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: [require('autoprefixer')]
                        }
                    }
                ]
            },
        ]
    }
}

方案二:html-inline-css-webpack-plugin

npm i html-inline-css-webpack-plugin -D
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HTMLInlineCSSWebpackPlugin = require("html-inline-css-webpack-plugin").default;

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    }),
    new HtmlWebpackPlugin(),
    new HTMLInlineCSSWebpackPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  }
}

3.tree shaking的使用和原理

摇树原理就是把有用的打包到bundle里去,把没用的在uglify阶段删除。摇树原理用到了DCE

DCE (Elimination) 包括以下几种形式:

  • 代码不会执行,不可到达
  • 代码执行结果不会被用到
  • 代码只会影响死变量(只写不读)

生产环境下默认开启tree-shaking

css摇树,需要配合css提取插件使用

我自己尝试了一下感觉并不好用,引了bootstrap结合自己的css,结果只能获取其中一个样式,另一个样式被干掉了,目前没有找到解决方法,于是先放弃了css摇树
找到上面的解决方法就是通过glob-all传入多个参数,处理多路径文件

安装:

npm install -D purifycss-webpack purify-css glob-all

webpack.config.js

const glob = require('glob-all');
const purifycssWebpack = require('purifycss-webpack');

// Make sure this is after ExtractTextPlugin!
new purifycssWebpack({
  paths: glob.sync([path.resolve('./src/*.html'),path.resolve('./src/*.js')])
}),

:注意插件顺序:html文件生成 > css提取 > css摇树

4.scope hoisting使用和原理分析

模块转化分析:

  • 被webpack转换后的模块会带上一层包裹
  • import会转换成__webpack_require

scope hoisting原理:

将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突。
通过scope hoisting可以减少函数声明代码和内存开销

scope hoisting使用

Webpack4 mode设为production会默认开启scope hoisting;必须是es6语法,commonjs不支持

5.代码分割

使用场景

  • 抽离相同代码到同一个共享块
  • 脚本懒加载,使得初始下载的代码更小

懒加载js脚本

方式一:commonJS: require.ensure
方式二:ES6:动态 import(目前还没有原生支持,需要babel转换)
下载插件:

npm install @babel/plugin-syntax-dynamic-import --save-dev
{
    plugins:['@babel/plugin-syntax-dynamic-import'],
}

6.多页面打包通用方案

动态获取 entry 和设置 html-webpack-plugin 数量
利用glob.sync

npm i glob -D
//引入glob
const glob=require('glob');
const path = require('path');
//引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
//动态设置entry,htmlwebpackplugin
const setMPA=()=>{
    const entry={};
    const HtmlWebpackPlugins=[];
    const entryFiles=glob.sync(path.join(__dirname,'./src/*/index.js'));
    Object.keys(entryFiles).map((index)=>{
        const entryFile=entryFiles[index];
        const match=entryFile.match(/src\/(.*)\/index\.js/);
        const pageName=match&&match[1];
        entry[pageName]=entryFile;
        HtmlWebpackPlugins.push(
            new HtmlWebpackPlugin({
                filename: path.join(__dirname, `dist/${pageName}.html`),//输出文件名
                template: path.join(__dirname,`src/${pageName}/index.html`),
                chunks:[pageName],//我的理解是一个入口就是一个chunk
                inject: true,//是否注入css,js,true表示在打包完成的 [pageName].html 内自动引入 chunks 为 [pageName] 的css,js
                minify: { //压缩html
                  removeComments: true,
                  collapseWhitespace: true,
                  removeAttributeQuotes: true,
                  minifyCss: true, //——>此处的minifyCss/js是为了压缩[pageName].html页面内的内嵌css/js,并不会对外链的css/js有影响
                  minifyJs: true
                },
                // 通过CommonsChunkPlugin持续处理多个块的必要条件
                chunksSortMode: 'dependency',
            })
        )
    })
    return {entry,HtmlWebpackPlugins}
}
const {entry,HtmlWebpackPlugins} = setMPA();
module.exports = {
    entry:entry,
    plugins:[].concat(HtmlWebpackPlugins)//将HtmlWebpackPlugins添加到plugins的数组中
}

7.devtool:

一般来说:生产环境推荐使用 none.
对于开发环境推荐使用cheap-module-source-mapeval-source-map
source-mapinline-source-map会暴露源码.
nosources-source-map 会隐藏源码

image

8.提取公共资源

基础库分离,减少代码冗余,提高加载速度
通过cdn导入,不打包在包内
利用 SplitChunksPlugin 进行公共脚本分离
他是webpack4内置的,替代 CommonsChunkPlugin 插件,CommonsChunkPlugin 已弃用

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000, //——>最小尺寸必须大于此值,默认30000B
      maxSize: 0,
      minChunks: 1, //—>其他entry引用次数大于此值,默认1,个人理解minChunks指的是被不同entry引入的次数,为1时,适合分离 node_moudles 里的第三方库
      maxAsyncRequests: 5, //——> 异步请求的chunks不应该超过此值
      maxInitialRequests: 3, //—-->entry文件请求的chunks不应该超过此值(请求过多,耗时)
      automaticNameDelimiter: '~', //——>自动命名连接符
      name: true,  //——>生成文件名
      cacheGroups: {  //——>它决定生成的文件
        commons: {  // 抽离自己写的公共代码
            chunks: "initial",
            name: "common", // 打包后的文件名,任意命名
            minChunks: 2,//最小引用2次
            minSize: 0 // 只要超出0字节就生成一个新包
        },
        vendors: {  // 抽离第三方插件
          test: /[\\/]node_modules[\\/]/,  //限制范围,可以是正则,匹配出需要分离的包
          name: 'vendor',  // 打包后的文件名,任意命名
          priority: 10  //优先级,多个分组冲突时决定把代码放在哪块,防止和自定义的公共代码提取时被覆盖,不进行打包
        }
      }
    }
  }
}

chunks 值为initial , asyncall

  • initial 入口chunk,同步引入的库进行分离
  • async 异步chunk,异步引入的库进行分离,忽略同步引入的库(默认)
  • all: 所有引入的库进行分离(推荐)

我的个人博客,有空来坐坐

你可能感兴趣的:(webpack4进阶知识点(一))