webapck

webpack基本配置

vue-cli create-react-app
只需要简单地配置就可以使用jsx和typescript等一些前端新语法

配置webpack.config.js文件

  • entry(项目入口)
    字符串,如entry:"./src/index.js"
    数组形式: 如entry:[react, react-dom],可以把数组中的多个文件打包转换为一个chunk
    对象形式,如果需要配置的是多页的应用,或者抽离出指定模块作为指定公共代码,需要采用这种形式,属性名是占位符[name]的值
entry: {
  main:'./src/index2.js',
  second: './src/index2.js',
  vendor:['react', 'react-dom']
}
  • output(出口文件)
    会告诉webpack在哪里输出所创建的bundle.js以及如何命名
out:{
    path:path.join(__dirname, './dist'),
    name: 'js/bundle-[name]-[hash].js,
    chunkFilename: 'js/[name].chunk.js',
    publicPath:'/dist/'

  }
  • module(模块的处理)
    webpack只能处理js文件,所以要对传入的模块做一些预处理,用webpack的“loader”’去识别新的用法
    loader的作用和基本用法
    webpack中,loader的配置主要在module.rules中进行,这是一个数组,每一个rule做了两件事
    识别文件类型,来确定具体处理该数据的loader(Rule.test属性)
    使用相关的loader对文件进行相关的操作转换(Rule.use属性)
    比如我们想要处理react中的jsx语法
module: {
  rules:[{
    test: /(\.jsx|\.js)/,  //表示匹配规则,是一个正则表达式
    use:{        //表示针对匹配文件将使用处理的loader
      loader: "babel-loader",  
      options: {
        presets: ["es2015", "react"]
      }
    }
  }]
}

常用的loade
module.rules识别各种新语法
转换编译:script-loader, babel-loader,ts-loader,coffee-loader
处理样式:style-loader,css-loader,less-loader,sass-loader,postcss-loader
处理文件:raw--loader,url-loader,file-loader
处理数据:csv-loader,xml-loader
处理模板语言:html-loader,pug-loader,jade-loader,markdown-loader
清理和测试:mocha-loader,eslint-loader

  • plugin(loader不能做的处理都能交给plugin来做)
const CleanWebpackPlugin = require("clean-webpack-plugin")

{

  ...

  plugin:[
    new webpack.DefinePlugin({
      "process.env" : {
        NODE_ENV: JSON.stringify("production")
      }
    }),
    new CleanWebpackPlugin(["js"], {

      root: __dirname + "/stu/",
      verbose: true,
      dry: false
    })
  ]
}

常见的plugins:
const HtmlWebpackPlugin = require('html-webpack-plugin')
HtmlWebpackPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
CleanWebpackPlugin

一些辅助开发的相关属性
  devtool:打包后的代码和原始代码存在较大的差异,此选项控制是否生成以及如何生成sourcemap
  devserver:通过配置devserver选项,可以开启一个本地服务器
  watch:启用watch模式后,webpack将持续监听热河已经解析文件的更改,开发是开启会很方便
  watchoption:用来定制watch模式的选项
  performance:打包后命令行如何展示性能提示,如果超过某个大小是警告还是报错

  • 对于webpack配置,要区分开发环境还是产环境
    为了避免重复应该提取公共代码

-所以一般有这么几个文件
webpack.config.js
webpacl.dev.js
webpack.prod.js
webpack.common.js

1、webpack.base.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'index.js'
    },
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: [
                        ['@babel/preset-env', {
                            'useBuiltIns': 'entry'
                        }]
                    ],
                    plugins: ['@babel/plugin-transform-runtime']
                }
            }
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        }),
        new CopyWebpackPlugin([{
            from: 'static',
            to: 'static'
        }, ])
    ],
    stats: {
        children: false
    }
}

2、webpack.config.js

const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const devConfig = require('./webpack.dev.config')
const proConfig = require('./webpack.pro.config')

module.exports = (env, argv) => {
    let config = argv.mode === 'development' ? devConfig : proConfig;
    return merge(baseConfig, config);
};

3、webpack.dev.config.js

module.exports = {
    devtool: 'cheap-module-eval-source-map'
}

4、webpack.pro.config.js

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
    plugins: [
        new CleanWebpackPlugin()
    ]
}

基本配置

拆分配置和merge
处理样式
启动本地服务
处理图片
处理ES6
模块化

  • 拆分配置和merge
    webpack-merge,用于将配置文件进行合并
npm install webpack-merge

配置(手动指定config)
package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config ./build/prod.config.js",
    "dev": "webpack-dev-server --open --config ./build/dev.config.js"
  },
  • 处理样式
    样式预处理,指的是在开发中使用到的一些预编译语言,如SCSS. LESS等,在项目打包过程中再将这些预编译语言转换为CSS
    在module.rules
 {
       test: /\.css$/,
       // loader 的执行顺序是:从后往前
       use: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
},{
       test: /\.less$/,
         // 增加 'less-loader' ,注意顺序
         use: ['style-loader', 'css-loader', 'less-loader']
   }
  • 启动本地服务
    安装
npm install --save-dev webpack-dev-server

运行

npx webpack-dev-server
 devServer: {
        port: 8080,
        progress: true,  // 显示打包的进度条
        contentBase: distPath,  // 根目录
        open: true,  // 自动打开浏览器
        compress: true,  // 启动 gzip 压缩

        // 设置代理
        proxy: {
            // 将本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': 'http://localhost:3000',

            // 将本地 /api2/xxx 代理到 localhost:3000/xxx
            '/api2': {
                target: 'http://localhost:3000',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    }

为了方便,我们通常会在package.json文件中写入一项命令配置本地服务启动。

"scripts": {
    "dev": "webpack-dev-server",
}

通过命令npm run dev就可以挂载我们指定的目录,从而启动本地服务了。

  • 处理图片
    安装依赖
npm i -D file-loader

在module.rules

{
    test: /\.(png|svg|jpg|gif)$/,
    use: {
        loader: 'file-loader',
        options: {
            name:'assets/[name].[ext]',
        }
    }
},
  • 处理ES6
    使用babel处理es6语法
    安装
npm install –save-dev babel-loader @babel/core

webpack.cofig.js配置

module: {
rules: [
{
test: /.js$/,
exclude: /node_modules,
//node_modules的js文件不用ES6转化为ES5
loader: "babel-loader"
}
]
}

webpack配置多入口

const path = require('path');
module.exports={
    //入口文件的配置项
    entry:{
        entry:'./src/entry.js',
        //这里我们又引入了一个入口文件
        entry2:'./src/entry2.js'
    },
    //出口文件的配置项
    output:{
        //输出的路径,用了Node语法
        path:path.resolve(__dirname,'dist'),
        //输出的文件名称
        filename:'[name].js'
    },
    //模块:例如解读CSS,图片如何转换,压缩
    module:{},
    //插件,用于生产模版和各项功能
    plugins:[],
    //配置webpack开发服务功能
    devServer:{}
}

webpack抽离压缩css文件

需要安装以下插件

mini-css-extract-plugin //把css抽离成单独的文件
optimize-css-assets-webpack-plugin  //把抽离出来的css代码压缩
terser-webpack-plugin   //压缩js代码

uglifyjs-webpack-plugin作用: 压缩is代码,不支持压缩es6
terser-webpack-plugin作用:压缩is代码,支持压缩es6

需要安装的loader
MiniCssExtractPlugin.loader 把css抽离成单独的文件

const path = require('path');
const HtmlWebpackPlugin  = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const Webpackbar = require('webpackbar');
module.exports = {
    // production模式自动压缩html,js,css,不用额外使用terser-webpack-plugin来压缩js
    // 但是如果要分离css,不管是dev还是prod都需要使用mini-css-extract-plugin
    // 但是如果要压缩分离出来的css,不管是dev还是prod都需要使用optimize-css-assets-webpack-plugin
    mode: 'development',
    entry: {
        main: './src/index.js'
    },
    output: {
        filename: '[name]_[hash:8].js',
        path: path.resolve(__dirname,'../build'),
        publicPath: './'
    },
    plugins:[
        // 打包之后自动生成index.html文件
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './src/index.html'
        }),
        // 打包之前自动删上一次的打包结果
        new CleanWebpackPlugin(),
        // 打包时候的进度条
        new Webpackbar({color: 'purple'}),
        // 抽离css
        new MiniCssExtractPlugin({
            filename: "css/[name]_[hash:8].css",
            chunkFilename: "[id].css"
        }),
        // 压缩css
        new OptimizeCssAssetsPlugin(),
        // 压缩js
        new TerserJSPlugin(),
    ],
    module: {
        rules:[
            {
                test:/\.css$/,
                use: [
                    // 这里一定要使用MiniCssExtractPlugin.loader才能达到抽离css的效果
                    {
                        loader: MiniCssExtractPlugin.loader,
                    },
                    'css-loader',
                    'postcss-loader',
                    'less-loader'
                ]
            }
        ]
    }
}

webpac抽离公共代码和第三方代码

CDN内容分发网络

项目中分别有a.js, b.js, page1.js, page2.js这四个JS文件, page1.js 和 page2.js中同时都引用了a.js, b.js, 这时候想把a.js, b.js抽离出来合并成一个公共的js,然后在page1, page2中自动引入这个公共的js,怎么配置如下:
optimization(优化),与module,output(出口),plugins(插件)同级
optimization下面minimizer是压缩css,splitChunks的common配置
optimization下面vendor配置抽离第三方代码

module.exports = {
  //...
 
  //优化项配置
  optimization: {
    // 分割代码块
    splitChunks: {
      cacheGroups: {
 
        //公用模块抽离
        common: {
          chunks: 'initial',
          minSize: 0, //大于0个字节
          minChunks: 2, //在分割之前,这个代码块最小应该被引用的次数
        },
        
        //第三方库抽离
        vendor: {
          priority: 1, //权重
          test: /node_modules/,
          chunks: 'initial',
          minSize: 0, //大于0个字节
          minChunks: 2, //在分割之前,这个代码块最小应该被引用的次数
        }
      }
    }
  }
}

webpack实现异步加载JS

module chunk bundle 的区别

module -各个源码文件,webapck中一切皆模块
chunk -多个模块组件的,如entry import() splitChunk
bundle最终的输出文件

webpack优化构建速度

优化babel-loder
InnorePlugin
noParse
happyPack
ParallelUglifyPlugin
自动刷新

happyPack

  1. happyPack多线程打包
  • JS单线程,开启多线程打包
  • 提高构建速度,特别是多核CPU
  1. ParallelUglifyPlugin多进程压缩JS
  • webapck内置Uglify工具压缩js
  • js单线程,开启多进程压缩更快
  • 和happyPack同理
  1. 关于开启多进程
    项目较大,打包较慢,开启多进程能提高速度
    项目较小,开启多进程会降低速度(进程开销)
    按需使用

webpack配置热更新

自动刷新

  watchOptions: {
        ignored: /node_modules/, // 忽略哪些
        // 监听到变化发生后会等300ms再去执行动作,防止文件更新太快导致重新编译频率太高
        // 默认为 300ms
        aggregateTimeout: 300,
        // 判断文件是否发生变化是通过不停的去询问系统指定文件有没有变化实现的
        // 默认每隔1000毫秒询问一次
        poll: 1000
    }
  1. 热更新
    自动刷新:整个网页全部刷新,速度较慢
    自动刷新:整个网页全部刷新,状态会丢失
    热更新:新代码生效,网页不刷新,状态不丢失
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');
 plugins: [
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('development')
        }),
        new HotModuleReplacementPlugin()
    ],
    devServer: {
        port: 8080,
        progress: true,  // 显示打包的进度条
        contentBase: distPath,  // 根目录
        open: true,  // 自动打开浏览器
        compress: true,  // 启动 gzip 压缩

        hot: true,

        // 设置代理
        proxy: {
            // 将本地 /api/xxx 代理到 localhost:3000/api/xxx
            '/api': 'http://localhost:3000',

            // 将本地 /api2/xxx 代理到 localhost:3000/xxx
            '/api2': {
                target: 'http://localhost:3000',
                pathRewrite: {
                    '/api2': ''
                }
            }
        }
    },

何时使用DllPlugin

前端框架如Vue React,体积大,构建慢
较稳定,不常升级版本
同一个版本只构建一次即可,不用每次都重新构建
webpack已内置DllPlugin支持
DllPlugin-打包出dll文件
DllReferencePlugin

webpack优化构建速度

webpack优化构建速度(可用于生产环境)
优化babel-loader
IgnorePlugin
noParse
happyPack
ParellelUqlifyPlugin

webpack优化构建速度(不用于生产环境)

自动刷新
热更新
DllPlugin

webpack性能优化-产出代码

体积更小
合理分包,不重复加载
速度更快,内存使用更少

  {
                test: /\.(png|jpg|jpeg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        // 小于 5kb 的图片用 base64 格式产出
                        // 否则,依然延用 file-loader 的形式,产出 url 格式
                        limit: 5 * 1024,

                        // 打包到 img 目录下
                        outputPath: '/img1/',

                        // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
                        // publicPath: 'http://cdn.abc.com'
                    }
                }
            },

webapck性能优化-产出代码

小图片base64 编码
bundle加hash
懒加载
使用prodction
Scope Hosting
提取公共代码
IngorePlugin
使用CDN加速

Tree-Shaking

自动开启代码压缩
Vue React等会自动删掉调试代码,(如开发环境的warning)
启动Tree-Shaking

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容