webpack看这一篇就够了

webpack看这一篇就够了

一、什么webpack?

简单来说,就是一个前端的打包工具。

在webpack看来,万事万物皆JS;图片是JS,css是JS……

官方网站链接

webpack.jpg
  • 对比gulp与webpack

相比自动化工具gulp而言,webpack的侧重点不同。

gulp侧重于前端开发的整个过程的控制管理,像是一条流水线,整个产品从无到有,都要受它的管控。

而webpack更侧重于模块打包,像一个模块打包机,把开发中的所有资源(图片、js文件、css文件等)都可以看成模块,将浏览器不识别的文件(scss/ts/vue等),通过loader(加载器)和plugins(插件)对资源进行处理,打包为一个或多个模块。

  • 常用的模块化开放方案
  • 前端:
    • requirejs——AMD,依赖前置,准备工作全部做完开始执行,用define定义模块,用require调用模块,在html中调用js文件用data-main属性。AMD不支持返回函数,只能导出对象,是异步的。
    • seajs——CMD,依赖就近,后期requireJS也支持了CMD规范,所以CMD渐渐不用了。
    • ES6:moudle(export import)——ECMA,用export或者export default导出,用import导入。这种方法最简单快捷,可以利用webpack中的babel转成es5的。
  • 服务端
    • commonJS——用module.exports将模块导出,可以导出对象、函数、ES5类,但是不能导出ES6类,用require导入模块。是同步的。
  • 模块化方式的优点
  1. 解决文件之间的以来关系。
  2. 避免命名冲突、解决全局变量级全局函数泛用的现象。
  3. 解决代码的服用性。
  4. 更好的分离,按需加载。

通常来讲,在webpack中会区分几个不同的环境进行打包:

  • 开发环境:src

  • 测试环境:test

    • 压力测试

    • 灰度测试

      ……

  • 生产环境:dist

二、简单总结常用的功能

  1. 初始化项目,生成package.json
npm init -y
  1. 安装 webpack和webpack-cli
cnpm install webpack webpack-cli -D

注:-D : --save-dev , 当前依赖要安装到开发环境中 devDependencies

​ -S : --save , 当前依赖要安装到生产环境中 Dependencies

  1. 创建src文件夹(开发环境的目录)

src文件夹中必须要有一个入口文件,eg:main.js

  1. 创建webpack.config.js文件

因为webpack在执行的时,默认会到跟目录下面的webpack.config.js(相当于gulpfile.js)文件

  1. webpack.config.js文件的配置项

    process.env查看环境变量,环境变量NODE_ENV未设置时,默认为undefined

    const path = require("path");
    
    // 配置入口文件和出口文件地址
    const PATH = {
        app:path.join(__dirname,".//src/main.js"),//路径拼接
        build:path.join(__dirname,"../dist")
    }
    
    // 配置webpack
    module.exports = {
        // 入口的配置
        entry:{
            name:PATH.app
        },
        // 出口配置
        output:{
            path:PATH.build,
            //filename:"[name].js"
            //name名与entry中的一致
             //判断当前是开发环境还是生产环境,
            filename: process.env.NODE_ENV == "development" ? "js/[name].[hash:8].js" : "js/[name].js"
        }
    }
    
  2. 打包命令(初级、基本使用)

npx webpack  

npx: 默认从当前文件的node_modules中找到相对应的模块

打包后生成的文件.jpg
  1. scripts中的命令运行

    • 将webpack.config.js中的配置,拆分到config中

    eg: base.config.js——对应开发与生产环境

    ​ dev.config.js——对应开发环境

    ​ pro.config.js——对应生产环境

    执行命令:

    npx webpack --config config/base.config.js
    
    config.png
    • 在package.json中添加配置项
     "scripts": {
        "dev": "webpack-dev-server --progress --config config/dev.config.js",
        "build": "webpack --progress --config config/pro.config.js"
      }
    

    经过上面的简化配置,运行时只需要输入npm run build就可以了

    注:--config:指定文件的配置 --progress为显示加载进度

  2. plugins:常用的插件

webpack中凡是用插件的地方都必须要在plugins中进行使用

  • html-webpack-plugin——打包引入js后的html文件(需要依赖webpack-cli,所以提前安装了webpack-cli)

    cnpm install html-webpack-plugin -D 
    
  • clean-webpack-plugin——打包时,清空上一次打包的内容

    cnpm install clean-webpack-plugin -D
    
  • copy-webpack-plugin——将开发环境的静态资源(img/css)拷贝到dist目录下

    cnpm install copy-webpack-plugin -D
    
  • extract-text-webpack-plugin——抽离css 优化

    cnpm install extract-text-webpack-plugin@next -D
    
  • 安装 vue-loadervue-template-compiler处理单文件组件

    cnpm install -D vue-loader vue-template-compiler
    
  • base.config.js添加配置

const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
 plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: "./public/index.html",
            filename: "index.html",
            //添加小图标
            favicon:"./favicon.ico"
        }),
        new CopyWebpackPlugin([
            {
                context: path.join(__dirname, "../public"),
                from: "**/*",
                to: path.join(__dirname, "../dist"),
                //忽略文件
                ignore: ["index.html"]
            }
        ]),
       //将定义过的其它规则复制并应用到 .vue 文件里相应语言的块。
        new VueLoaderPlugin()
    ],
  1. loader:模块的转换

转换浏览器不识别的文件配置项时,要在module中配置;

  • 处理vue的loader

    • 在rules中添加配置项
    {
        test: /\.vue$/,
        use: ['vue-loader']
    }
    
  • 处理JS的loader

    • babel-loader
    • @babel/core
    • @babel/preset-env
    cnpm install babel-loader @babel/core @babel/preset-env -D
    

    安装之前需要package.json同级目录下创建.babelrc文件,进行如下配置

    {
        "presets": [
            [
                //低版本的转换 ES6 => ES5
                "@babel/preset-env",
                {
                    //设置浏览器版本
                    "targets":{
                        //兼容到所有浏览的最后2个版本
                        "browsers":["last 2 version"]
                    }
                }
          ]
        ]
    }
    
    • base.config.js添加以下配置
     {
         test: /\.js$/,
         loader: "babel-loader"
     },
    
    • 在单页面开发中如果用async await不识别时,需要安装以下依赖:
    regeneratorRuntime.png
    cnpm i @babel/plugin-transform-runtime --save-dev
    cnpm i @babel/runtime --save
    

    在.bablerc文件中添加配置"plugins":["@babel/plugin-transform-runtime"]

    {
        "presets": [
            [
                "@babel/preset-env",
                {
                    "targets": {
                        "browsers": ["last 2 version"]
                    }
                }
            ]
        ],
        "plugins": ["@babel/plugin-transform-runtime"]
    }
    
  • 处理css的loader

    • style-loader
    • css-loader
    • sass-loader
    • postcss-loader
    • autoprefixer

    在解析sass的时候除了需要sass-loader之外,还需要一个特别重要的模块node-sass

    注:autoprefixer 解析CSS文件,自动添加css样式的浏览器前缀到CSS内容里

    cnpm install style-loader css-loader sass-loader node-sass postcss-loader autoprefixer -D
    
  • dev.config.js添加配置 ,做CSS的抽离

    rules: [
        {
            test: /\.(css|scss)$/,
            use: ["style-loader", "css-loader", "sass-loader"]
        }
    ]
    
  • pro.config.js添加配置——见文章第五点

  • 处理图片的loader

    • url-loader

    • file-loader

    • url-loader file-loader的区别

    url-loader一般用来解析体积较小的图片,可以通过options中的limit来设置图片的大小
    如果图片大于limit的大小,则用file-loader进行解析,file-loader一般用来解析比较大的图片

    cnpm install url-loader file-loader -D
    
    • base.config.js添加配置
    {
        test: /\.(jpg|gif|png|svg)$/,
        use: {
            loader: "url-loader",
            options: {
                limit: 2048,
                // name是图片原始的名称  ext是文件的后缀名
                name: "img/[name].[ext]"
            }
      }
    },
    
  • base.config.js中对字体的配置

    {
        test: /\.(woff|woff2|svg|ttf|eot)$/,
            use: {
                loader: "url-loader",
                    options: {
                        name: "font/[name].[ext]"
                    }
            }
    },
    
  1. webpack-merge合并webpack配置项

配置文件被分成了许多不同的部分,那么必须以某种方式来组合他们,通常就是合并数组和对象,webpack-merge很好的做到了这一点。

cnpm install webpack-merge -D

webpack-merge做了两件事:它允许连接数组并合并对象,而不是覆盖组合。

  1. webpack-dev-server 创建开发环境的服务
cnpm install webpack-dev-server -D
  1. 处理非模块化的插件
cnpm install script-loader exports-loader -D
  • 在base.config.js中的rules引入
{
    //引入非模块化的插件
    test: require.resolve('zepto'),
    //转化成模块的方式
    loader: 'exports-loader?window.Zepto!script-loader'
}

三、base.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");

/*
    __dirname:当前文件的绝对路径
    path.join:做路径的拼接
*/

//配置入口文件和出口文件地址
const PATH = {
    app: path.join(__dirname, "../src/main.js"),//路径拼接
    build: path.join(__dirname, "../dist")
}

//配置webpack
module.exports = {
    //入口的配置
    entry: {
        app: PATH.app
    },
    //出口配置
    output: {
        path: PATH.build,
        filename: "[name].js"//name名与entry中的一致
    },
    //使用插件配置项
    plugins: [
        new HtmlWebpackPlugin({
            template: "./public/index.html",//基于当前根目录下寻找
            filename: "index.html",//打包完成后生成的文件名
            hash:true,//为引入js的地址添加后缀,用于清楚缓存
            inject:true,//true(默认)/body/head,是否讲js文件嵌入到html中。可以制定添加到body或head后面
            //chunks:["入口属性名"],//指定打包的文件
            //excludeChunkds:["my"],//打包除了入口属性为my的文件
            title: "M站开发",//在html中title标签中设置<%= htmlWebpackPlugin.options.title%>
            minify:{
                removeComments:true,//清除注释
                removeAttributeQuotes:true,//清除双引号
                collapseWhitespace:true,//进行折叠,并且去除空格
            }
        }),
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin([
            {
                // 指定拷贝文件的目录
                context: path.join(__dirname, "../public"),
                from: "**/*",
                to: path.join(__dirname, "../dist"),
                //忽略文件
                ignore: ["index.html"]
            }
        ])
    ],
    //别名的配置项
    resolve: {
        //文件引入的优先级,从左到右,没找到vue时会去找js,scss,art……
        extensions: [".vue",".js", "scss", "art", "css", "json"],
        //别名的配置
        alias: {
            "@": path.join(__dirname, "../src")
        }
    },
    //loader的配置 转换浏览器不识别的文件配置项
    module: {
        //规则
        rules: [
            {
                //引入非模块化的插件
                test: require.resolve('zepto'),
                //转化成模块的方式
                loader: 'exports-loader?window.Zepto!script-loader'
            },
            //一个对象代表一个规则
            {
                test: /\.js$/,
                loader: "babel-loader",
                exclude: path.join(__dirname, "../node_modules")
            },
            {
                test: /\.art$/,
                loader: "art-template-loader"
            },
            //处理图片的loader
            {
                test: /\.(png|jpg|gif|svg)$/,
                use: {
                    loader: "url-loader",
                    options: {
                        limit: 2048,
                        // name是图片原始的名称  ext是文件的后缀名
                        name: "img/[name].[ext]"
                    }
                },
                exclude: path.join(__dirname, "../node_modules")
            },
            //处理字体的配置项(包括iconfont字体库)
            {
                test: /\.(woff|woff2|svg|ttf|eot)$/,
                use: {
                    loader: "url-loader",
                    options: {
                        name: "font/[name].[ext]"
                    }
                },
                exclude: path.join(__dirname, "../node_modules")
            }
        ]
    }
}

四、开发环境dev.config.js

  • dev.config.js
const baseConfig = require("./base.config");
const webpackMerge = require("webpack-merge");
const path = require("path");

//合并
const config = webpackMerge(baseConfig,{
    //当前的环境
    mode:"development",
    module:{
        rules:[
            {
                test:/\.(css|scss)$/,
                //cssloader的执行顺序 从右到左 从下到上
                use:["style-loader","css-loader","sass-loader"],
                exclude:path.join(__dirname,"../node_modules")
            }
        ]
    },
    //服务器的配置项
    devServer:{
        //自动打开浏览器
        open:true,
        //设置端口号
        port:9000
    }
})

module.exports = config;

五、生产环境pro.config.js

  • 使用postcss时,要在package.json同级目录下创建postcss.config.js文件
module.exports = {
    plugins: [
        //自动添加浏览器前缀
        require("autoprefixer")({
            overrideBrowserslist: [
                "defaults",
                "Android 4.1",
                "iOS 7.1",
                "Chrome>31",
                "ff>31",//火狐
                "ie>=8",
                "last 2 versions",
                ">0%"
            ]
        })
    ]
}
  • pro.config.js
const path = require("path");
const baseConfig = require("./base.config");
const webpackMerge = require("webpack-merge");
const ExtractTextWebpackplugin = require("extract-text-webpack-plugin");
const config = webpackMerge(baseConfig, {
    mode: "production",
    module: {
        rules: [
            {
                test: /\.(css|scss)$/,
                //css抽离
                use: ExtractTextWebpackplugin.extract({
                    //解析css、sass,postcss用来加浏览器的前缀
                    use: ["css-loader", "postcss-loader", "sass-loader"],
                    fallback: "style-loader",
                }),
                exclude: path.join(__dirname, "../node_modules")
            }
        ]
    },
    plugins: [
        new ExtractTextWebpackplugin({
            filename: "css/[name].[hash:8].css"//取打包后,哈希值的后8位
        })
    ]
})

module.exports = config;

你可能感兴趣的:(webpack看这一篇就够了)