webpack基础使用

# webpack基本使用
## 样式资源引入
import"index.css"
{
	test: /\.css$/,
	use: [
		// 创建style标签,将js中的样式资源添加到header中生效,且不是直接写入到html中,是通过js执行时写入
		'style-loader',
		// // 将css变成commonjs模块加载到js中,里面的内容是样式字符串
		'css-loader'
		
	]
}

处理css和js中的图片用到file-loader、url-load

{
    test: /\.(png|jpg|jpeg)$/,
    use: 'url-loader',
    options: {
        // 图片大小小于8KB时,将图片转为Base64处理,base64会导致图片变大
        limit: 8 * 1024
    }
}
  • 打包其他资源
    如在css中的字体文件,但是打包后会将这些文件名更改为MD5
{
    exclude: /\.(css|js|html)$/,
    loader: 'file-loader',
    options: {
        name: '[hash:10].[ext]'
    }
}

分离css文件
用到的插件min-css-extract-plugin,需要在将style-loader换成是MinCssExtractPlugin.loader

{
    test: /\.css$/,
    // use中的执行顺序是从下至上
    use: [
        MinCssExtractPlugin.loader, // 提取js中的css,分离成单独的文件
        // 将css变成commonjs模块加载到js中,里面的内容是样式字符串
        'css-loader',

    ]
},

new MinCssExtractPlugin({
    filename: 'public/index.css'
})

修改css的兼容性
引入loader,postcss-loader,引入loader中的插件postcss-preset-env
帮助postcss在package.json中找到browserlist中的配置,在postcss的官网中可以找到相关配置

{
    test: /\.css$/,
    // use中的执行顺序是从下至上
    use: [
        MinCssExtractPlugin.loader, // 提取js中的css,分离成单独的文件
        // 将css变成commonjs模块加载到js中,里面的内容是样式字符串
        'css-loader',
        {
            loader: 'postcss-loader',
            plugin: () => [
                require('postcss-preset-env')()
            ]
        }
    ]
},

package.json

  "browserlist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  }

环境变量不是webpack中的环境变量,而是node中的环境变量,即procss.env.NODE_ENV

压缩css
用到的插件
optimize-css-assest-webpack-plugin
使用

new OptimizeCssAssetsWebpackPlugin()

js 语法检查

依赖eslint-loader eslint airbnb eslint-config-airbnb-base eslint-plugin-import

配置
{
    test: /\.js$/
    loader: "eslint-loader",
    exclude: /node_modules/
    options: {
        fix: ture // 自动修复错误
    }
}

设置的规则在package.json中eslintConfig
airbnb github上有规则
npm上有现成eslint-config-airbnb
一般用的是es6,所以用eslint-config-airbng-base

JavaScript兼容性处理

使用插件babel-loader、@babel/core

基本的兼容性处理

@babel/preset-env

{
    loader: 'babel-loader',
    exclude: /node_modules/,
    options: {
        preset: ['@babel-preset-env']
    }
}

全部兼容性处理

@babel/profill
可以在js中引入import “@babel/profill”,但是是全部引入
按需加载需要引入core-js

{
    loader: 'babel-loader',
    exclude: /node_modules/,
    options: {
        preset: [
            '@babel-preset-env',
            {
                useBuildIns: 'usage',
                // 指定coreJS版本
                corejs: {
                    version: 3
                },
                targets: {
                    chrome: '60',
                    firefox: '60',
                    ie: '9',
                    edge: '17'
                }
            }
        ]
    }
}
压缩HTML
new HtmlWebpackPlugin({
    template: './src/index.html',
    minify: {
        //移除空格
        collapseWhitespace: true,
        // 移除注释
        removeCommnets: true
    }
})

webpack性能优化

概览

开发环境

  • 打包构建速度
  • 优化代码调试

生产环境

  • 优化构建打包速度
  • 优化运行速度

HMR 模块热替换

一个模块发生变化,一个模块变化只更新变化的模块

    devServer: {
        content: resolve(__dirname, 'build'),
        compress: true,
        port: 3000,
        // open: true,
        hot: true // 开启HMR模式

    },

样式文件,需要使用style-loader,style-loader中内部实现HMR模式
js文件, 默认不实用HMR模式

需要修改js代码,添加对HMR的功能

if(module.hot) {
    module.hot.accept('./print.js', function() {
        console.log('loader print.js');
    });
}

HTMl文件: 不会产生变化

解决办法在entry中引入,html变化,整体都会刷新

开发环境下调试代码source-map

在webpack.config.js根对象下配置

{
    devtool: 'inline-source-map'
}
  • source-map
    能够提供错误代码的准确位置,和源代码的准确位置
  • inline-source-map 内联到文件末尾
    与source-map基本一致,只是内联而已
  • hidden-source-map 外联,单独生成.map文件
    提示错误是构建后的电脑及错误原因
  • eval-source-map 每一个都生成一个对应source-map, 在eval函数中执行
    跟inline-source-map一致
  • nosources-source-map 外部
    能找到代码的准确信息,但是找不到任何源码的信息
  • cheap-source-map 外部
    与inline差不多,但是cheap只是提供到代码行,而inline会找到准确位置
  • cheap-module-source-map 外部
    错误代码的准确位置,和源代码的准确位置,回家loader的source-map加入

这些可以两两组合

开发环境
速度 eval > inline > cheap
速度快

  • eval-cheap-source-map
  • eval-source-map (一般选择这个)
    调试更友好
  • source-map
  • cheap-module-source-map
  • cheap-source-map

oneOf

修改webpack中的rule
只会匹配一个loader,同事

{
    module: {
        rules: [
            {
                test: /\.js$/
                exclude: /node_modules/,
                enforce: 'pre', // 优先执行
                loader: 'eslint-loader',
                options: {
                    fix: true
                }
            },
            {
                oneOf: [

                ]
            }
        ]
    }
}

// eslint-disable-next-line
忽略eslint检查的warn

缓存

{
    output: {
        filename: 'build.[hash:10].js',
        path: resolve(__dirname, 'build')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MinCssExtractPlugin({
            filename: 'public/index.[hash:10].css'
        }),
        new OptimizeCssAssetsWebpackPlgin()
    ],
}

当出现变化时全部都重新构建,相关联的hash也变化,因为js和css使用同一个hash
babel缓存catchDireactory:true

{
    output: {
        filename: 'build.[chunkhash:10].js',
        path: resolve(__dirname, 'build')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MinCssExtractPlugin({
            filename: 'public/index.[chunkhash:10].css'
        }),
        new OptimizeCssAssetsWebpackPlgin()
    ],
}

关联时也会全部重新构建
根据文件来单独hash用contenthash

{
    output: {
        filename: 'build.[contenthash:10].js',
        path: resolve(__dirname, 'build')
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new MinCssExtractPlugin({
            filename: 'public/index.[contenthash:10].css'
        }),
        new OptimizeCssAssetsWebpackPlgin()
    ],
}

代码树摇

前提条件必须es6,production环境,webpack自动tree shaking
在package.json中写sideEffects: false,所有代码都可以进行tree shaking,会把css文件文件干掉
sideEffects:[’*.css’]

代码分割

多入口

{
    entry: {
        index: './src/index.js',
        test: './src/test.js'
    },
    output: {
        filename: './js/[name].[contenthash:10].js',
        path: resolve(__dirname,'dist')
    }
}

单入口
webpack.config.js 根
自动分析多入口中有没有公用的文件


optimization: {
    // 将node_modules中代码单独打包成一个chunk
    splitChunks: 'all'
}

通过js将一个文件单独打包成一个chunk

import('./simple.js').then(() => {
    console.log('load success!');
});

懒加载

在代码中import

btn.onclick = () => {
    import(/* webpackChunkname: 'test'*/).then(() => {
        console.log('load success!');
    });
}

预加载

btn.onclick = () => {
    import(/* webpackChunkName: 'test', webpackPrefetch: true */).then(() => {
        console.log('load success!');
    });
}

PWA 离线 渐进式开发

采用workbox技术
插件workbox-webpack-plugin

const WorkWebpackPlugin = require('work-webpack-plugin');
{
    Plugins: [
        new WorkWebpackPlugin({
            /*
            帮助serviceworker快速启动,删除旧的serviceworker
            生成一个serviceworker文件
            */
            clientClaim: true,
            skipWwaiting: true
        });
    ]
}

在代码中

if('serviceWorker' in navigater) {
    navigater.serviceWorker.register('./serviceworker.js').then(() => {
        console.log('regist successful');
    }).catch(() => {
        console.log('regist error!');
    });
}

多进程打包

用到的loader: thread-loader
用在babel-loader中

{
    test: /\.js$/
    exclude: /node_modules/,
    use: [
        'thread-loader',
        {
            loader: 'thread-loader',
            options: {
                workder: 2 // 两个进程
            }
        },
        {
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
            preset: [
                '@babel-preset-env',
                {
                    useBuildIns: 'usage',
                // 指定coreJS版本
                    corejs: {
                        version: 3
                    },
                    targets: {
                        chrome: '60',
                        firefox: '60',
                        ie: '9',
                        edge: '17'
                    }
                }
            ]
        }
    ]
}

有利有弊
开启也是需要时间,进程之间通信也是要成本的
只有工作需要消耗大量时间时才使用

external

打包时忽略的一些包
webpack.config.js根

externals: {
    // 忽略掉指定的包名,jquery
    jquery: 
}

dll

对一个库进行打包,第三方库打包,可以打包成不同chunk
webpack.dll.js

const { resolve } = require('path');
const webpack = require('webpack');
module.exports = {
    entry: {
        jquery: ['jquery']
    },
    output: {
        filename: '[name].js',
        path: resolve(__dirname, 'dll'),
        library: '[name]_[hash]'
    },
    plugin: [
        new webpack.DllPlugin({
            name: '[name]_[hash]', // 映射库的名称
            path: resolve(__name, 'dll/manifest.json') // 提供jquery的包的映射关系
        })
    ]
}

webpack.config.js

const webpack = require('webpack');
const addAssetsHtmlWebpackPlugin = require('add-html-webpack-plugin');
{
    plugin: [
        // 高速webpack哪些库不参与打包,使用时的名称也将会被更改
        new webpack.DllReferencPlugin({
            manifest: resolve(__dirname, 'dll/manifest.json')
        }),
        new addAssetsHtmlWebpackPlugin({
            filepath: resolve(__dirname, 'dll/jquery.js')
        });
    ]
}

其他

{
    output: {
        filename: '/js/[name].js',
        path: resolve(__dirname, 'dist'),
        publicPath: '/',
        chunkFilename: '[name]_chunk.js', // 非入口chunk的名称,
        labraryTarget: 'window' // node commonjs
    }
}

resolve

{
    resolve: {
        alias: {
            $css: resolve(__dirname, 'src/css')
        },
        extensions: ['.js', '.json'],
        modules: [
            'node_modules',

        ]
    }
}

devServer

{
    // 项目构建后的目录
    contentBase: resolve(__dirname, 'dist'),
    // 启动gizp压缩
    compress: true,
    // 端口好
    port: 3000,
    // 自动打开浏览器
    open: true,
    // 开启HMR功能,
    hot: true,
    // 监视contentbase目录变化重载
    watchContentBase: true,
    // 不要启动服务器日志
    clientLogLevel: 'none',
    quiet: true, // 不要打印其他不必要的信息
    watchOptions: {
        ignored: /node_modules/
    },
    overlay: false, // 出现错误不要全屏提示,
    proxy: {
        '/api': {
            target: 'http://localhost:5000',
            pathRewrite: {
                '^/api': '' // 路径重写
            }
        }
    }
}

optimizions

const TerserWebpackPlugin = requrie('terser-webpack-plugin');
{
    optimizions: {
        splitChunk: 'all', // 
        miniSize: 30 * 1024, // 最小分割size
        maxSize: 0, // 都要分割,
        minChunck: 1, // 最少被引入一次
        maxAsyncRequest: 5, // 最大并行加载数
        maxInitialRequest: 3, // 入口最大请求并行数量
        automaticNameDelimiter:  "~",// 命名链接规则
        name: true, // 可以使用,
        cacheGroups: { // 分割chunk组
            // node_modules中的文件会打包到vendor中
            vendors: {
                test: /[\\/]node_modules[\\/]/,
                priority: -10
            },
            default: {
                // 要提取的chunk至少被引用两次
                minChunk: 2,
                priority: -20,
                // 如果当前要打包的模块,和之前已经被提取的模块是同一个,复用不必在打包
                reuseExistingChunk: true, 
            }
        },
        // 将当前模块记录其他模块的hash值单独打包到一个文件中将runtime文件
        runtimeChunk: {
            name: entrypoint=> 'runtime-${entryport.name}'
        },
        minimizer: [
            new TerserWebpackPlugin(
                cache: true, // 开启缓存
                parallel: true, // 开启多进程打包
                sourceMap: true
            )
        ]
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值