webpack(一)-基础配置

286 阅读4分钟

webpack详解

概念

官网上这么解释webpack的,“webpack 是一个用于现代 JavaScript 应用程序的_静态模块打包工具_。当 webpack 处理应用程序时,它会在内部构建一个 依赖图(dependency graph),此依赖图对应映射到项目所需的每个模块,并生成一个或多个 bundle。”

作用

代码转换

js es6代码转成es5
@babel/core @babel/preset-env @babel/polyfill autoprefixer
css loader对sass less等的转换

文件优化 图片处理

压缩代码体积
optimize-css-assets-webpack-plugin
uglifyjs-webpack-plugin
去除console debugger 调试标识等

代码分割

公共模块的抽离
懒加载

模块合并

多个模块合成一个模块

服务部署

本地启动服务 热更新 解决跨域问题
webpack-dev-server

代码校验

eslint代码校验

自动发布

打包完成自动发布

基础配置

配置webpack.config.js文件

// path: Node.js 核心模块,用于操作文件路径。
const path = require('path');
//将打包好的文件更新到html模板中
const HtmlWebpackPlugin = require('html-webpack-plugin');
//抽离css的插件
const MiniCssExtractPlugin = require('mini-css-extrac-plugin');
// autoprefixer 自动填充css3前缀
//压缩css
let optimize = require('optimize-css-assets-webpack-plugin');
// 压缩js
let UglifyJsPlugin = require('uglifyjs-webpack-plugin');
let webpack = require('webpack');
// babel转es5 babel-loader @babel/core @babel/preset-env @babel/polyfill
/* 
exporse-loader 把变量暴露全局的方式 
内联的loader 
pre 前置执行loader 
normal 普通loader 
post后置loade
*/
//file-loader 会生成图片到build下 并把路径返回 适用于import引入图片
// html-withimg-loader 适用于html img引入图片
// url-loader 做图片限制 小于多少用base64转化

//cleanWebpackPlugin
//copyWebpackPlugin
//bannerPlugin 内置插件
module.exports = {
    //优化项
    optimization: {
        minimizer: [
            new UglifyJsPlugin(
                {
                    //添加缓存
                    cache: true,
                    //开启并发压缩
                    parallel: true,
                    //源码映射,方便调试
                    sourceMap: true
                }
            ),
            new optimize()
        ]
    },
    devtool: 'source-map', //增加映射文件 可以帮我们调试源代码 有单独的文件
    //devtool: 'eval-source-map', //不会产生单独的文件 但是会显示行和列
    //devtool: 'cheap-module-source-map', //产生后可以保留起来 不会显示行和列
    //devtool: 'cheap-module-eval-source-map', //没有行跟列 跟html集成 不会产生单独的文件
    //打包时有两种模式,分别为:production 和 development
    mode: '',
    //打包的入口
    entry: './path/to/my/entry/file.js', //单页打包
    // entry: {
    //     home: './path/to/my/entry/file.js',
    //     other: './path/to/my/entry/file.js'
    // }, 
    //多页打包
    // path: 打包后的文件输出路径
    // filename: 打包后的文件名称
    watch: true,
    watchOptions:{
        poll: 1000, //每秒询问频次
        aggreatement: 500, //防抖 
        ignored: /node_modules/ //不需要进行监控的文件
    },
    output: {
        //path.resolve 将路径解析为一个绝对路径
        path: path.resolve(__dirname, 'dist'),
        filename: 'webpack.bundle.[hash].js',
        publicPath: 'www.img.com' //公共路径
    },
    // 开发服务器的配置 需要添加 webpack-dev-server
    devServer: {
        port: 3000, //服务启动端口
        progress: true, //是否展示进度条
        contentBase: 'path', //指向文件路径
        compress: true, //启动文件压缩
    },
    plugins: [ //webpack 所有的插件
        new HtmlWebpackPlugin({
            template: path, //模板地址
            filename: index.html, //打包后文件
            minify: { //将打包后的文件最小化
                removeAttributeQuotes: true, //去掉所有双引号
                collapseWhitespace: true //将代码折成一行
            },
            hash: true // 加上hash值 避免出现缓存
        }),
        new MiniCssExtractPlugin({
            filename: min.css //打包后文件
        }),
        new webpack.ProvidePlugin({ //在每个模块中都注入$
            $: 'jquery'
        })
    ],
    externals: {
        jquery: $
    }, //外部引入 不需要打包
    //样式处理 默认只能解析js 并不能解析css
    module: {
        noParse: /jquery/, //不去解析jquery依赖包
        //loader 全局变量引入
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                // use: 'file-loader'
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 200*1024,
                        outputPath: '/img/'
                    }
                }
            },
            {
                test: /\.html$/,
                use: 'html-withimg-loader'
            },
            {
                test: require.resolve('jquery'),
                use: 'expose-loader?$!jquery'
            },
            //css loader 解决 @import语法
            // style-loader 把css插入head标签中
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader, //如果单独抽出来需要配置此项
                    {
                        loader: 'style-loader',
                        options: {
                            insertAt: 'top' //解析好的文件插入位置
                        }
                    },
                    'css-loader',
                    'postcss-loader',
                ]
            },
            {
                test: /\.js$/, //新建文件在.eslintrc.json 配置eslint配置
                use: {
                    loader: 'eslint-loader',
                    options: {
                        enforce: 'pre', // previous 强制这个loader在之前执行 post 在之后执行
                    }
                },
            },
            {
                test: /\.js$/,
                use: {
                    loader: 'bable-loader',
                    options: { //用babel-loader需要把es6转es5
                        presets: [ //预设
                            '@babel/prest-env',
                        ],
                        plugins: [
                            '@bable/plugin-proposal-class-properties', //支持class声名
                            //generator 
                            // 装饰器 等 去官网上自己找plugins吧 附在网址 https://babeljs.io/
                        ]
                    },
                },
                include: path.resolve(__dirname, 'src'), //需要打包的路径
                exclude: /node_modules/, //不需要打包的路径
            }
        ]
    },
    // 跨域配置
    devServer:{
        before(app){}, //做数据mock
        proxy: {
            // '/api': 'http://localhost:3000' //代理配置
            '/api':{
                target: 'http://localhost:3000',
                pathRewrite:{'/api': ''}, //重新请求
            }
        }
    },
    resolve: { //解析第三方包
        modules: [path.resolve('node_modules')],
        alias:{ //别名
            bootstrap: 'dist/css/bootstrap.css'
        }
    }
};

postcss.config.js

module.exports = {
  plugins: [require('autoprefixer')]
}

打包过程

打包一个文件时,首先会检查打包的文件是否在缓存(installedModules对象)中,如在缓存,直接返回,如不在缓存进行打包相关操作(modules[moduleId].call(module.exports, module, module.exports, webpack_require_)) 返回打包后的文件 (return modules[moduleId] )

更改webpack 配置文件命令

webpack --config webpack.config.my.js

引入第三方包的方式

1、expose-loader 挂在window上
2、providePlugin 给每个模块注入
3、cdn引入 可以引入不进行打包 externals

抽离公共代码

第三方与公共代码的抽离

optimization:{
slitChunks: {
  cacheGroups:{
  commmon: {
  chunks: 'initial',
  minSize: 0, //最小大小
  minChunks: 2 //用过多少次去提取公共包
  },
  vendor: {
  priority: 1,
  test: /node_modules/,
  chunks: 'initial',
  minSize: 0, //最小大小
  minChunks: 2 //用过多少次去提取公共包
  }
  }
}
}

懒加载

添加动态载入插件 plugin-syntax-dynamic-import

//原理
import('test.js').then();

热更新

new webpack.NamedModulesPlugin() //打印更新的模块
new webpack.HotModuleReplacementPlugin() //热更新

if(module.hot){
    module.hot.accept('./source', ()=>{
    console.log('update');
    let str = require('source');
    console.log(str);
    })
}

好了,webpack的基础配置就到这里了,下一章偏原理些。