webpack4温习总结

webpack是一个模块打包器,可以根据入口文件,随着依赖关系将所有文件打包成js文件。

首先需要node环境,百度一下自己安装

webpack官网地址:https://www.webpackjs.com

首先,建立一个文件,叫webpack1(不能叫webpack,否则初始化报错)

初始化:

npm init -y

初始化之后,文件夹中会出现一个package.json文件

之后安装webpack

npm i -D webpack

webpack4还需要安装一个webpack-cli

npm i -D webpack-cli

之后在根目录下创建一个src文件夹,里面放的是源码,里面放一个index.js,是入口文件;

在根目录建一个dist文件,用来盛放打包后的文件,dist文件夹中再放一个index.html文件;

再在跟目录下创建一个webpack.config.js文件,当做webpack的配置文件

在src/index.js中随便写点代码:

import _ from 'lodash';
import "./style/index.css";//loader=>css-loader module style-loader
import "./style/a.scss";
function createDomElement(){
    let dom = document.createElement('div');
    dom.innerHTML=_.join(["aicoder.com","好!","线下实习"],"");
    // dom.className="box";
    dom.classList.add("box");
    return dom;
}

let divDom = createDomElement();

document.body.appendChild(divDom);

在webpack.config.js中作出简单配置:

const path = require("path");
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"development",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { //告诉webpack,当import,require遇到.css文件时,用css-loader、style-loader处理一下
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: ["style-loader","css-loader","sass-loader"],//loader的使用数据是从右向左的
            }
        ]
    }
}

在dist/index.html中引入打包生成的main.js

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script src="./main.js"></script>
</body>
</html>

当然我们还在src/style/中加了index.css和a.sass文件,

如果想让webpack打包js之外的文件,需要安装对应的loader

css需要css-loader(用来解析css文件)、style-loader(用来将打包好的css文件用style标签引入)

scss文件需要 sass-loader 和 node-sass

一口气安装了:

npm i -D css-loader style-loader sass-loader node-sass

之后执行npx webpack

dist文件中就会出现打包好的main.js

然后就可以打开dist/index.html看一下效果。

如果我们想执行自己的自定义命令来让webpack打包,我们可以在package.json的script中配置一下命令,如:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"npx webpack -c webpack.config.js"
  },

之后我们执行 npm run build就可以让webpack打包了

上面的-c webpack.config.js指的是 webpack是根据哪个文件的配置打包的

----------------------------------------------------------------------------------------------------------------------------

由于webpack是将所有的依赖文件打包成一个文件,当我们想调试css样式时,我们很难在控制台看到某一句代码是来自哪个源文件的,所以我们需要开启sourceMap,

在webpack.config.js中国这样配置:

module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: ["style-loader",{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    }

然后执行npm run build 在控制台查看css样式,就可以清晰的看到某个样式,是来自哪一个文件(index.css还是a.scss一目了然)

------------------------------------------------------------------------------------------------------------

另外我们一般还会用到postcss 以及 autuoprefixer

postcss 可以对css进行预处理 校验css 以及自动添加前缀 可以提前使用css的一些新特性

首先安装 (我们此处只用了 自动添加前缀的插件 所以额外安装了autoprefixer)

npm i -D postcss-loader
npm install --save-dev autoprefixer

在webpack.config.js中添加对应配置:

module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: ["style-loader",{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    }

----------------------------------------------------------------------------------------------------

将css文件单独抽离出来

npm install --save-dev mini-css-extract-plugin

一般我们都是在生产环境将css文件单独抽离出来的,所以我们在根目录中创建webpack.product.config.js文件,用来配置生产环境下的webpack配置,将上面的webpack.config.js中的配置复制一份过来,做以下改变:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name].[hash].css',
            chunkFilename:'[id].[hash].css',
        })
    ],
}

执行如下命令:

npx webpack --config webpack.product.config.js

就可以用这个配置文件打包了

当然,如果我们需要多次打包 这样输入命令显得有点复杂,我们可以在package.json中的script中增加一个脚本命令:

"dist": "npx webpack --config webpack.product.config.js"

之后,运行npm run dist与上述命令等效

----------------------------------------------------------------------------------------------------------------------------------

css压缩:(生产环境才能用到)

安装这个插件

npm install optimize-css-assets-webpack-plugin --save-dev

在webpack.product.config.js配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name].css',
            chunkFilename:'[id].css',
        })
    ],
    optimization:{
        minimizer:[new OptimizeCSSAssetsPlutin({})]
    }
}

之后执行 npm run dist打包 即可压缩css代码

-------------------------------------------------------------------

js压缩:(生产环境用)

npm i -D uglifyjs-webpack-plugin

在webpack.product.config.js中加入配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            // {
            //     test: /\.js$/,
            //     loader: 'babel-loader',
            //     exclude: /node_modules/,
            // }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name].css',
            chunkFilename:'[id].css',
        })
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

然后执行npm run dist 就行

----------------------------------------------------------------------------------

将es6转化转义成es5

安装:

npm i -D babel-loader babel-core babel-preset-env

在根目录新建一个.babelrc文件

配置上:

{
"presets": ["@babel/env"]
}

在webpack.product.config.js中配置:

rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            }
        ]

--------------------------------------------------------------------------

如何将每次打包的js和css文件 自动引入到html文件中:

npm install html-webpack-plugin -D

在config.js中配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.[hash].js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name][hash].css',
            chunkFilename:'[id][hash].css',
        }),
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }

        })
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

当然,需要在src下简历一个index.html模板

然后,执行npm run dist 即可

-----------------------------------------------------------------------

清理dist目录

每次打包 都会生成一些新的打包文件,从而之前的没用的打包文件也会保留下来,很不爽,所以我们需要一个自动清理dist目录的插件

npm install clean-webpack-plugin --save-dev

在config.js中配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.[hash].js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name][hash].css',
            chunkFilename:'[id][hash].css',
        }),
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

然后再次构建,dist目录会被清理一下再生成打包文件

--------------------------------------------------------------------------------------------------------

webpack处理图片

首先 打包时处理不了图片这种二进制文件的 路径,我们需要用一个file-loader插件

安装:

npm install --save-dev file-loader

在config.js中配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.[hash].js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {//处理图片 路径
                test:/\.(png|svg|gif|jpg|jpeg)$/,
                use:[
                    'file-loader'
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name][hash].css',
            chunkFilename:'[id][hash].css',
        }),
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

这样,打包时,图片路径就不会报错了

打包后,dist中会多出打包后的图片文件

那么,如果我们想将图片进行优化呢?

我们需要借助一个插件:

npm install image-webpack-loader --save-dev

config.js配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.[hash].js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {//处理图片 路径
                test:/\.(png|svg|gif|jpg|jpeg)$/,
                include:[path.resolve(__dirname,'src/')],
                use:[
                    'file-loader',
                    {
                        loader: 'image-webpack-loader',
                    },
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name][hash].css',
            chunkFilename:'[id][hash].css',
        }),
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

--------------------------------------------------------------------------------

将图片进一步优化处理 成base64

将图片转化成base64的dataurl的形式,提高页面性能

npm install --save-dev url-loader

我们只需要将file-loader变成url-loader即可:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.[hash].js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {//处理图片 路径
                test:/\.(png|svg|gif|jpg|jpeg)$/,
                include:[path.resolve(__dirname,'src/')],
                use:[
                    {
                        loader:'url-loader',
                        options:{//小于10000字节的图片转换成base64格式
                            limit:10000
                        }
                    },
                    {
                        loader: 'image-webpack-loader',
                    },
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name][hash].css',
            chunkFilename:'[id][hash].css',
        }),
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

----------------------------------------------------------------------------------

如何将不同环境的webpack配置文件合并,将共同配置共用?

npm install --save-dev webpack-merge

首先,我们需要改变配置文件的结构,之前是webpack.config.js和webpack.product.config.js分别充当 开发和生产环境配置,

现在我们分为webpack.common.js、webpack.dev.js、webpack.prod.js 这三个文件分别写着公共配置、开发环境特有配置、生产环境特有配置

下面写出栅格文件的内容:

webpack.common.js:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {//处理图片 路径
                test:/\.(png|svg|gif|jpg|jpeg)$/,
                include:[path.resolve(__dirname,'src/')],
                use:[
                    {
                        loader:'url-loader',
                        options:{//小于10000字节的图片转换成base64格式
                            limit:10000
                        }
                    },
                    {
                        loader: 'image-webpack-loader',
                    },
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    
    
}

webpack.dev.js:

const path = require("path");
const merge = require('webpack-merge');//引入webpack-merge参数
const common = require('./webpack.common');//将webpack.common.js引入
let devConfig={
    mode:"development",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: ["style-loader",{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    }
}

module.exports=merge(common,devConfig);//第一个参数是基本配置 后面的参数是当前配置

webpack.prod.js:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const merge = require('webpack-merge');//引入webpack-merge参数
const common = require('./webpack.common');//将webpack.common.js引入
let prodConfig={
    mode:"production",//模式是开发环境
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.[hash].js",
        path:path.resolve(__dirname,"dist")
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: [
                    MiniCssExtractPlugin.loader,{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename:'[name][hash].css',
            chunkFilename:'[id][hash].css',
        }),
    ],
    optimization:{
        minimizer:[
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                /**
                 *  sourceMap 和 devtool: 'inline-source-map', 冲突
                 */
                sourceMap: false, // set to true if you want JS source maps,
                /**
                 *  extractComments 导出备注
                 */
                extractComments: 'all'
            }),
            new OptimizeCSSAssetsPlutin({})
        ]
    }
    
}

module.exports=merge(common,prodConfig);

还有在package.json中记得把执行命令的--config改一下

{
  "name": "webpack1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "npx webpack --config webpack.dev.js",
    "dist": "npx webpack --config webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.6.0",
    "@babel/plugin-transform-runtime": "^7.6.0",
    "@babel/preset-env": "^7.6.0",
    "@babel/runtime-corejs2": "^7.6.0",
    "autoprefixer": "^9.6.1",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "image-webpack-loader": "^6.0.0",
    "mini-css-extract-plugin": "^0.8.0",
    "node-sass": "^4.12.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^8.0.0",
    "style-loader": "^1.0.0",
    "uglifyjs-webpack-plugin": "^2.2.0",
    "url-loader": "^2.1.0",
    "webpack": "^4.39.3",
    "webpack-cli": "^3.3.8",
    "webpack-merge": "^4.2.2"
  },
  "dependencies": {
    "@babel/polyfill": "^7.6.0",
    "@babel/runtime": "^7.6.0",
    "lodash": "^4.17.15"
  }
}

------------------------------------------------------------------------------------------------------------------------------

js启用sourcemap

webpack4默认可以启用sourcemap

只需要在config文件中加上:(这个通常放在开发环境中)

devtool:'inline-source-map'

这样在开发环境下,就可以看到执行的js具体是在哪个文件下的第几行执行的

-----------------------------------------------------------------------------------------------------------------

监控文件变化,启用watch,当代码发生变化时,自动编译,自动打包

在webpack启动的时候 加上一个 --watch命令

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "npx webpack --watch --config webpack.dev.js",
    "dist": "npx webpack --config webpack.prod.js"
  },

-------------------------------------------------------------------------------------------------------------------

webpack-dev-server和热更新

webpack-dev-server提供了一个Web服务器,能够实加载,它内置了webpack的编译功能,是直接编译在内存里,而不是编译在dist文件里,

先安装webpack-dev-server

npm install --save-dev webpack-dev-server

在webpack.dev.js:

const path = require("path");
const merge = require('webpack-merge');//引入webpack-merge参数
const common = require('./webpack.common');//将webpack.common.js引入
const webpack = require('webpack');
let devConfig={
    mode:"development",//模式是开发环境
    devtool:'inline-source-map',//开启sourcemap  方便js调试
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    devServer: {
        contentBase: path.join(__dirname,"dist"), //告诉服务器 哪里提供内容,默认情况下将使用当前工作目录作为提供内容的目录
        port: 8080, //端口号设为8080, 默认也是8080
        clientLogLevel:'warning',//可能的值none、error、warning、info(默认值)
        hot:true,//启用webpack的模块热替换特性,这个需要配合webpack.HotModuleReplacementPlugin插件
        compress:true,//一切服务都启用gzip压缩
        host:'localhost',//指定使用一个host,默认是localhost,如果你希望服务器外部可访问0.0.0.0
        open:true,//是否打开浏览器
        overlay:{//出现错误或者警告的时候,是否覆盖页面线上错误消息
            warnings:true,
            errors:true
        },
        publicPath:'/',//此路径下的打包文件 可在浏览器上访问
        proxy:{
            "/api":{
                target:"http://192.168.0.102:8080",
                pathRewrite:{
                    "^/api":"/mockjsdata/5/api",
                    // /api/getuser => http://192.168.0.102:8080/mockjsdata/5/api/getuser
                }
            }
        },
        quiet:true,//启动quiet后,除了初始启动信息之外的任何内容都不会显示
        watchOptions:{//监视文件相关控制选项
            poll:true,//webpack使用文件系统(file system)获取文件改动的通知,在某些情况下不会正常工作
            ignored:/node_modules/,//忽略监控的文件夹,正则
            aggregateTimeout:300,//默认值,当第一个文件改变,会在重新构建前增加延迟


        }
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: ["style-loader",{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    },
    plugins:[
        new webpack.NamedModulesPlugin(),//更容易查看path 的估值
        new webpack.HotModuleReplacementPlugin(),//替换插件

    ]
}

module.exports=merge(common,devConfig);//第一个参数是基本配置 后面的参数是当前配置

之后执行 npx webpack-dev-server --config webpack.dev.js 就会打开服务器,另外需要注意的是,webpack-dev-server内置了webpack的打包功能,但是它时打包到了内存中,而不是dist文件中

当然每次这样执行命令太长了,就把它加到script的命令中:

"start": "npx webpack-dev-server --config webpack.dev.js"

-------------------------------------------------------------------------------------------------------------

babel优化

js启用babel转码:es6转化为es5

安装

npm i -D babel-loader babel-core babel-preset-env

在公共webpack.common.js中添加:

module: {
        rules: [
            {

          test: /\.js$/,

exclude: /node_modules/,

use:{

loader: 'babel-loader',

options:{

cacheDirectory:true,//开启缓存 加快babel转码

}

}

            },
            
        ]
    },

记得在根目录下创建一个.babelrc文件

{
    "presets": ["@babel/env"]
}

----------------------------------

另外 我们在项目中可能在多个模块中重复引用同个文件,这样当babel转码时会一次性将这些重复文件都转码过去,造成文件体积变大,此时需要用到插件,将这些公共的文件提取出来。

npm install babel-plugin-transform-runtime --save-dev
npm install babel-runtime --save

在.babelrc中配置:

{
    "presets": ["@babel/env"]
}

------------------------------------------------------------------------------------------

eslint校验:

安装:

npm install eslint  --save-dev
npm install eslint-loader --save-dev

以下是用到的额外的需要安装的eslint的解释器、校验规则等

npm i -D babel-eslint standard

在common.js中增加配置

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use:[{
                    loader: 'babel-loader',
                    options:{
                        cacheDirectory:true,//开启缓存 加快babel转码
                    }
                },{//一定要放在下面  先执行eslint检测 再转义  因为webpack是从后往前执行的
                    loader:'eslint-loader',
                    options:{
                        fix:true,//如有语法错误 自动修复
                    }
                }]
            },
            {//处理图片 路径
                test:/\.(png|svg|gif|jpg|jpeg)$/,
                include:[path.resolve(__dirname,'src/')],
                use:[
                    {
                        loader:'url-loader',
                        options:{//小于10000字节的图片转换成base64格式
                            limit:10000
                        }
                    },
                    {
                        loader: 'image-webpack-loader',
                    },
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    
    
}

在跟目录添加.eslintrc.js文件

module.exports={
    root:true,//是不是我们的根目录
    parserOptions: {
        parser:'babel-eslint'
    },
    env:{
        browser:true,
    },
    extends:[
        'standard'
    ],
    globals:{
        NODE_ENV:false
    },
    rules:{
        'generator-star-spacing':'off',
        'no-debugger': process.env.NODE_ENV === 'production' ? 'error':'off',
        //添加分号 必须
        'semi':['error','always'],
        'no-unexpected-multiline':'off',
        'space-before-function-paren':['error','never'],
        'quotes':[
            'error',
            'single',
            {
                'avoidEscape':true
            }
        ]
    }
}

在根目录加.eslintignore文件

/dist/
/node-modules/
/*.js

--------------------------------------------------------------------------------------------

resolve解析,当我们引入一个文件时,比如import _ from './src/dev.js'

我们可以将路径配置一个别名,方便引入模块

在common.js中可以加一条配置:

const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlutin=require('optimize-css-assets-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
module.exports={
    entry:"./src/index.js",//入口文件
    resolve:{
        alias:{
            '@':path.resolve(__dirname,'src/')
        },
        extensions:[".js",".vue",".json"],//默认.js  .json
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use:[{
                    loader: 'babel-loader',
                    options:{
                        cacheDirectory:true,//开启缓存 加快babel转码
                    }
                },{//一定要放在下面  先执行eslint检测 再转义  因为webpack是从后往前执行的
                    loader:'eslint-loader',
                    options:{
                        fix:true,//如有语法错误 自动修复
                    }
                }]
            },
            {//处理图片 路径
                test:/\.(png|svg|gif|jpg|jpeg)$/,
                include:[path.resolve(__dirname,'src/')],
                use:[
                    {
                        loader:'url-loader',
                        options:{//小于10000字节的图片转换成base64格式
                            limit:10000
                        }
                    },
                    {
                        loader: 'image-webpack-loader',
                    },
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title:"webpack 温习",//默认值webpack App
            filename:"main.html",//默认值index.html 是最终生成的文件名字
            template:path.resolve(__dirname,"src/index.html"),
            minify:{
                collapseWhitespace:true,//是否去空白
                removeComments:true,//是否移除注释
                removeAttributeQuotes:true,//移除属性的引号
            }
        }),
        new CleanWebpackPlugin(),//清理构建文件夹
    ],
    
    
}

---------------------------------------------------------------------------------

webpack 配置外部拓展(externals) cdn也可以全局引入

在common.js中再增加一个配置 已引入jquery为例

externals:{
        jquery:"jQuery",//写法有多种可以查一下
    },

这样就可以在main,js中import $ from 'jquery' 来全局引入jquery 另外这样做有个好处就是 jquery不会打包到bundle里去 大大减少文件体积

-----------------------------------------------------------------------------------------

如何让webpack打包后生成分析报表

安装

npm install --save-dev webpack-bundle-analyzer

在dev.js中配置

const path = require("path");
const merge = require('webpack-merge');//引入webpack-merge参数
const common = require('./webpack.common');//将webpack.common.js引入
const webpack = require('webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
let devConfig={
    mode:"development",//模式是开发环境
    devtool:'inline-source-map',//开启sourcemap  方便js调试
    output:{//出口文件时main.js,打包到当前目录的dist文件夹下
        filename:"main.js",
        path:path.resolve(__dirname,"dist")
    },
    devServer: {
        contentBase: path.join(__dirname,"dist"), //告诉服务器 哪里提供内容,默认情况下将使用当前工作目录作为提供内容的目录
        port: 8080, //端口号设为8080, 默认也是8080
        clientLogLevel:'warning',//可能的值none、error、warning、info(默认值)
        hot:true,//启用webpack的模块热替换特性,这个需要配合webpack.HotModuleReplacementPlugin插件
        compress:true,//一切服务都启用gzip压缩
        host:'localhost',//指定使用一个host,默认是localhost,如果你希望服务器外部可访问0.0.0.0
        open:true,//是否打开浏览器
        overlay:{//出现错误或者警告的时候,是否覆盖页面线上错误消息
            warnings:true,
            errors:true
        },
        publicPath:'/',//此路径下的打包文件 可在浏览器上访问
        proxy:{
            "/api":{
                target:"http://192.168.0.102:8080",
                pathRewrite:{
                    "^/api":"/mockjsdata/5/api",
                    // /api/getuser => http://192.168.0.102:8080/mockjsdata/5/api/getuser
                }
            }
        },
        quiet:true,//启动quiet后,除了初始启动信息之外的任何内容都不会显示
        watchOptions:{//监视文件相关控制选项
            poll:true,//webpack使用文件系统(file system)获取文件改动的通知,在某些情况下不会正常工作
            ignored:/node_modules/,//忽略监控的文件夹,正则
            aggregateTimeout:300,//默认值,当第一个文件改变,会在重新构建前增加延迟


        }
    },
    module: {
        rules: [
            { 
                test: /\.(sc|c|sa)ss$/,//scss,css,sass
                use: ["style-loader",{
                        loader:"css-loader",
                        options:{
                            sourceMap:true
                        }
                },{
                    loader:"postcss-loader",
                    options:{
                        ident:"postcss",//唯一标识,建议使用postcss
                        sourceMap:true,
                        plugins:(loader)=>[
                            require("autoprefixer")({overrideBrowserslist:["> 0.15% in CN"]}),//浏览器 份额大于0.15% 在中国 (已经包括IE8了)
                        ]
                    }
                },{
                    loader:"sass-loader",
                    options:{
                        sourceMap:true
                    }
                }],
            }
        ]
    },
    plugins:[
        new webpack.NamedModulesPlugin(),//更容易查看path 的估值
        new webpack.HotModuleReplacementPlugin(),//替换插件
        new BundleAnalyzerPlugin(),//生成打包报表
    ]
}

module.exports=merge(common,devConfig);//第一个参数是基本配置 后面的参数是当前配置

然后 打包一下,就会出现报表