webpack一文了解

快速的带各位同学入门这款自动化工具,看完之后你就懂了,你就真的懂了

一定要看看我粘贴的代码,注释都在里面写着呢,如果你是在那啥,就直接看看注释就行了也没问题

既然能看到这篇文章,你应该明白了一些webpack的基础了吧,我就直接开始写了

安装

我们的第一步就是安装webpack了,首先新建一个目录进去

npm init
// 或者使用yarn
yarn init 

然后我们

npm i -D webpack webpack-cli
// 或者使用yarn
yarn add -D webpack webpack-cli

最后我们就可以使用如下命令查看webpack版本了,如果安装上了的话

npx webpack -v

其实说webpack就完全在说loader一样,webpack必须使用loader才能工作,没有loader的webpack什么都做不了

在此之前我们再安装一下webpack的静态服务器吧

npm i -D webpack-dev-server

这个东西跟webpack是一个家族的,所以配置的时候直接再webpack的配置文件中写就行了

配置

文件根目录新建一个webpack.config.js文件,这是一基本内容

// 这就是一个js文件,所以直接使用js的语法就行了,不要以为这是个啥啥啥

for (let i = 0; i < 10000; i++) {
    // 我在这里写个for循环都没有问题,你明白吧
    console.log(i);
}

module.exports = {

}

配置package.json scripts

然后我们键入这些内容之后,我们直接运行一下webpack看看吧,在这之前我们配置一下package.json文件,因为方便啊

新增字段

我们去新增一个scirpts字段里面写上如上代码,然后我们就可以运行webpack看看了

npm run build
// yarn
yarn build

基本配置

不出意外的话,应该是执行完for循环之后就报错了,你明白吧,那么现在我们需要配置webpack了

const path = require("path")


module.exports = {
    // 可选的production 对应生成环境    指定这个东西后面可以有对应的插件进行判断mode优化
    // 比如说再production环境就需要去进行代码的压缩啊,图片的合并之类的,但生产环境只要打包资源就行了
    mode: "development",  // 开发环境
    // 入口文件,webpack打包必须需要的入口文件,所有的资源都是再入口文件引入然后webpack进行跟踪资源打包的
    // 后面你就懂了
    entry:"./src/main.js",
    output:{
        // 这是一个绝对路径,所以我们需要使用nodejs自带的模块path进行完成了
        // 代表打包到dist目录下
        path:path.resolve(__dirname,"dist"),
        // 入口文件以及里面引入的所有js代码都会被打包到一个文件
        // 这个字段可以为这个文件取一个名字,你没写这个字段我也不知道会发生些什么
        filename:"all.js",
        // 打包之后的html文件内加载资源的相对路径
        publicPath:"/assets/"
    }
}

你把这上面的一写,然后在新建一个src目录并新建一个main.js文件,然后我们随便写一点内容都行啊,然后就直接开始打包吧,比如说我这里main.js这样写的

for(let i=0;i<10000;i++){

}
console.log("作死完成");

然后我们直接开始打包吧

npm run build

跑起来,我们就会发现webpack已经帮我们打包好了,那么这就是我现在的目录结构了


文件

然后你会发现打包之后的文件咱也看不懂,咱也不敢问,老老实实学怎么用就行了吧,管他底层怎么实现的,然后我们先跑一下打包之后的文件试试能不能运行吧

cd dist
node all.js
done

然后这就完成了,因为这就是一个完整的打包流程了,之后就是加上各种loader啊插件啊让在打包的过程中给他转换语法啊加前缀啊合并啊压缩啊混肴啊等等等等,你明白吧

babel-loader 转换语法

首先说说第一个loader,就是webpack跟babel协作转换语法并打包的loader
那么首先我们需要安装如下工具

npm i -D @babel/core @babel/preset-env @babel/runtime @babel/plugin-transform-runtime babel-loader
// 然后安装polyfill
npm i @babel/polyfill

然后我们就开始配置我们的第一个loader吧,首先因为使用了babel我们需要在main.js中写一下高级语法

class Person {
    constructor(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    sayHello() {
        console.log("hello iam" + this.name + "  " + this.age + "   " + this.sex);
    }
}

new Person("suiyue",10,"男").sayHello();

然后我们开始配置loader了

const path = require("path")


module.exports = {
    // 可选的production 对应生成环境    指定这个东西后面可以有对应的插件进行判断mode优化
    // 比如说再production环境就需要去进行代码的压缩啊,图片的合并之类的,但生产环境只要打包资源就行了
    mode: "development",  // 开发环境
    // 入口文件,webpack打包必须需要的入口文件,所有的资源都是再入口文件引入然后webpack进行跟踪资源打包的
    // 后面你就懂了
    entry:"./src/main.js",
    output:{
        // 这是一个绝对路径,所以我们需要使用nodejs自带的模块path进行完成了
        // 代表打包到dist目录下
        path:path.resolve(__dirname,"dist"),
        // 入口文件以及里面引入的所有js代码都会被打包到一个文件
        // 这个字段可以为这个文件取一个名字,你没写这个字段我也不知道会发生些什么
        filename:"all.js",
        // 打包之后的html文件内加载资源的相对路径
        publicPath:"/assets/"
    },

    // 模块
    module:{
        // 规则
        rules:[
            {
                // 正则表达式匹配entry指定的js文件中使用import或者require引入的文件
                // 这里匹配的是引入文件后缀名为.js的文件
                test:/\.js$/,
                use:{
                    // 指定要处理的loader
                    loader:"babel-loader",
                    // 可以给这个loader传递一些参数
                    // 在这里就相当于babel.config.js
                    options:{
                        presets:["@babel/preset-env"],
                        plugins:["@babel/plugin-transform-runtime"]
                    }
                }
            }
        ]
    }
}

然后我们直接yarn build看看效果吧,然后你就会发现打包出来的all.js还是看不懂,。。。。
这需要明白一点就行了,我们不是写了一个Person类吗,我们就去all.js搜索这个类看看语法不就行了吗?

我是图片

我觉得当我把这张图片放在这里的时候,你应该已经懂了,这一看就知道是function``function构造器

然后因为接下来处理的资源需要一个完整的页面环境了,所以我们需要新建一个html页面了

image.png

这就是我目前的目录结构了,这时候我们需要提到一个插件了,对就是一个插件了

  • html-webpack-plugin --> 打包html文件

这个插件的作用就非常强大了,你知道吧,我们打包文件之后那么我们就需要在index.html文件中手动引入这些打包之后的资源了,你能忍吗?并且webpack还默认不会帮我们打包这个index.html文件
(搜索entry指定的js文件然后继续追寻对应的import或者required的js文件打包到一起)
所以说你总不可能告诉我你要 import "index.html"吧,这明显不科学啊,所以我们特别特别特别需要这款插件

npm i -D html-webpack-plugin

稍微改动了一下output选项下的js输出路径

const path = require("path")

// 命名尽量首字母大写
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
    // 可选的production 对应生成环境    指定这个东西后面可以有对应的插件进行判断mode优化
    // 比如说再production环境就需要去进行代码的压缩啊,图片的合并之类的,但生产环境只要打包资源就行了
    mode: "development",  // 开发环境


    // 入口文件,webpack打包必须需要的入口文件,所有的资源都是再入口文件引入然后webpack进行跟踪资源打包的
    // 后面你就懂了
    entry:"./src/main.js",



    output:{
        // 这是一个绝对路径,所以我们需要使用nodejs自带的模块path进行完成了
        // 代表打包到dist目录下
        path:path.resolve(__dirname,"dist"),
        // 入口文件以及里面引入的所有js代码都会被打包到一个文件
        // 这个字段可以为这个文件取一个名字,你没写这个字段我也不知道会发生些什么
        filename:"js/all.js",
        // 打包之后的html文件内加载资源的相对路径
        publicPath:"/assets/"
    },




    // 模块
    module:{
        // 规则
        rules:[
            {
                // 正则表达式匹配entry指定的js文件中使用import或者require引入的文件
                // 这里匹配的是引入文件后缀名为.js的文件
                test:/\.js$/,
                use:{
                    // 指定要处理的loader
                    loader:"babel-loader",
                    // 可以给这个loader传递一些参数
                    // 在这里就相当于babel.config.js
                    options:{
                        presets:["@babel/preset-env"],
                        plugins:["@babel/plugin-transform-runtime"]
                    }
                },
                // 一定要配置这个exclude选项,禁止babel去转换node_modules模块下的代码
                // 不然就是一大堆奇奇怪怪的错误
                exclude:/node_modules/
            }
        ]
    },

    // 所有插件都必须在plugins中new出来,这是一个数组
    plugins:[
        new HtmlWebpackPlugin({
            // 指定需要打包的html文件
            template:"public/index.html",
            // 输出的文件
            filename:"index.html"
        })
    ]
}

然后我们就可以在dist目录下看见我们的index.html是这样的了

图片

他就会自动引入所需要的css或者js等文件,因为目前还没有css文件所以就是这种情况,为什么是assets呢,是因为我们在output的publicPath指定的就是这个啊

  • webpack-dev-server配置

既然有了html了,我们就快速配置一下webpack-dev-server吧,这样的话能够热更新式的刷新页面了,在webpack配置文件中新增

image.png

然后我们就可以使用npm run dev看看效果了,你就会发现webpack已经开始使用http协议进行访问并且在编辑器里面实时更新代码浏览器也会实时刷新的,这就是体验了

  • css预处理器loader --> less-loader

关于less-loader就是用来打包less文件的,我们首先安装loader和其需要的依赖

npm i -D less-loader less css-loader mini-css-extract-plugin postcss-loader autoprefixer

这里我们需要通过css-loaderless-loader转换后的css代码处理一下,然后我们通过postcss-loader+autoprefixer给css的一些语法进行加前缀然后我们通过mini-css-extract-plugin插件导出为一个单独的css文件,同样的大家也可以使用style-loader给处理之后的css直接加载在对应标签的style属性上,但是我觉得还是到处为一个单独的css文件然后通过上面的html-webpack-plugin引入好一点,这里凭大家的爱好吧

大家一定要仔细看我的注释了哦,这次的loader什么的有点多都是用来操作css的,我们先配置出来然后在去写对应的less文件测试

const path = require("path")

// 到处html文件插件
const HtmlWebpackPlugin = require("html-webpack-plugin")

// 导出css样式插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin")



module.exports = {
    // 可选的production 对应生成环境    指定这个东西后面可以有对应的插件进行判断mode优化
    // 比如说再production环境就需要去进行代码的压缩啊,图片的合并之类的,但生产环境只要打包资源就行了
    mode: "development",  // 开发环境


    // 入口文件,webpack打包必须需要的入口文件,所有的资源都是再入口文件引入然后webpack进行跟踪资源打包的
    // 后面你就懂了
    entry: "./src/main.js",



    output: {
        // 这是一个绝对路径,所以我们需要使用nodejs自带的模块path进行完成了
        // 代表打包到dist目录下
        path: path.resolve(__dirname, "dist"),
        // 入口文件以及里面引入的所有js代码都会被打包到一个文件
        // 这个字段可以为这个文件取一个名字,你没写这个字段我也不知道会发生些什么
        filename: "js/all.js",
        // 打包之后的html文件内加载资源的相对路径
        publicPath: "/assets/"
    },




    // 模块
    module: {
        // 规则
        rules: [
            {
                test: /\.less$/,
                // 需要使用多个loader的时候use可以是一个数组了
                /* 
                    loader默认是从下到上处理对应的文件的
                    所以这里就是先使用less转换语法
                    然后通过postcss-loader给css代码自动加前缀
                    然后使用css-loader处理css代码
                    最后可以使用style-loader直接加载到对应标签的style属性上
                    我这里使用的是mini-css-extract-plugin到处为一个单独的css文件
                 */
                use: [
                    MiniCssExtractPlugin.loader,
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            //  通过postcss-loader的autoprefixer插件自动给需要兼容的css样式加前缀
                            plugins: [require("autoprefixer")]
                        }
                    },
                    "less-loader"
                ]
            },
            {
                // 正则表达式匹配entry指定的js文件中使用import或者require引入的文件
                // 这里匹配的是引入文件后缀名为.js的文件
                test: /\.js$/,
                use: {
                    // 指定要处理的loader
                    loader: "babel-loader",
                    // 可以给这个loader传递一些参数
                    // 在这里就相当于babel.config.js
                    options: {
                        presets: ["@babel/preset-env"],
                        plugins: ["@babel/plugin-transform-runtime"]
                    }
                },
                // 一定要配置这个exclude选项,禁止babel去转换node_modules模块下的代码
                // 不然就是一大堆奇奇怪怪的错误
                exclude: /node_modules/
            }
        ]
    },

    // 所有插件都必须在plugins中new出来
    plugins: [
        new HtmlWebpackPlugin({
            // 指定需要打包的html文件
            template: "public/index.html",
            // 输出的文件
            filename: "index.html"
        }),
        new MiniCssExtractPlugin({
            // 会将所有的样式文件也合并到一个,这里需要指定一下对应样式文件的名称
            filename: "css/[name].css",
        })
    ],

    // 这是webpack-dev-server的配置
    devServer: {
        // 绑定端口3000
        port: 3000,
        // 自动打开浏览器到指定网页
        open: true,
        // 热更新
        hot: true,
        // 代表网站根目录那样的,主目录是哪里
        // 这里是dist,所以会自动加载已经打包好的文件
        // 直接填你output中的path就行了
        contentBase: "dist"
    }
}

然后我们可以在src目录下新建一个less目录,随便写点什么,这是我的目录结构

结构

使用npm run build打包出来就是这样的

关于打包css文件


image.png

然后说说当我们使用第三方框架的时候需要导入一些字体文件或者svg等图标文件是怎么导入的呢?

  • url-loader & file-loader --> 导入字体文件,图片文件

首先我们需要安装这个loader

npm i -D url-loader file-loader

然后我们需要在rules中添加两个规则

            {
                test:/\.(woff|woff2|ttf|eot|svg)$/,
                loader:"url-loader"
            },
            {
                // 忽略大小写
                test:/\.(png|jpe?g|gif)$/i,
                use:{
                    loader:"url-loader",
                    options:{
                        // 小于8kb的图片将被转换成dataurl格式
                        limit:8192
                    }
                }
            },
  • clean-webpack-plugin

这个插件有什么用呢?可以在打包之前删除一些文件,这就非常方便了,我们正好需要在打包之前删除dist目录下的所有的文件和目录然后让他重新生成出来

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

然后我们就需要使用这个插件了,非常简单的,最上面引入这个插件

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

然后直接在plugins中new出来

// 会默认寻找你webpack配置文件中output.path目录然后清空
new CleanWebpackPlugin()

结束,就是这么easy

那么关于一个项目中需要用到的loader基本上已经介绍完成了,然后大家可以根据不同的项目配置不同的loder进行使用,比如说react中需要配置jsx语法后缀的loader,vue中需要配置vue后缀的文件loader,这里我不是很熟悉react,我放一下vue的webpack自己手动的配置吧

配置vue的开发环境需要这三个依赖

npm install -D vue-loader vue-template-compiler vue-style-loader

我这里直接就发配置完成之后的代码了

const path = require("path")

// 到处html文件插件
const HtmlWebpackPlugin = require("html-webpack-plugin")

// 导出css样式插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
    // 可选的production 对应生成环境    指定这个东西后面可以有对应的插件进行判断mode优化
    // 比如说再production环境就需要去进行代码的压缩啊,图片的合并之类的,但生产环境只要打包资源就行了
    mode: "development",  // 开发环境


    // 入口文件,webpack打包必须需要的入口文件,所有的资源都是再入口文件引入然后webpack进行跟踪资源打包的
    // 后面你就懂了
    entry: "./src/main.js",



    output: {
        // 这是一个绝对路径,所以我们需要使用nodejs自带的模块path进行完成了
        // 代表打包到dist目录下
        path: path.resolve(__dirname, "dist"),
        // 入口文件以及里面引入的所有js代码都会被打包到一个文件
        // 这个字段可以为这个文件取一个名字,你没写这个字段我也不知道会发生些什么
        filename: "js/all.js",
        // 打包之后的html文件内加载资源的相对路径
        // 注释掉这个恶心的选项
        //publicPath: "/assets/"
    },




    // 模块
    module: {
        // 规则
        rules: [
            {
                test:/\.(woff|woff2|ttf|eot|svg)$/,
                loader:"url-loader"
            },
            {
                // 忽略大小写
                test:/\.(png|jpe?g|gif)$/i,
                use:{
                    loader:"url-loader",
                    options:{
                        // 小于8kb的图片将被转换成dataurl格式
                        limit:8192
                    }
                }
            },
            {
                test: /\.less$/,
                // 需要使用多个loader的时候use可以是一个数组了
                /* 
                    loader默认是从下到上处理对应的文件的
                    所以这里就是先使用less转换语法
                    然后通过postcss-loader给css代码自动加前缀
                    然后使用css-loader处理css代码
                    最后可以使用style-loader直接加载到对应标签的style属性上
                    我这里使用的是mini-css-extract-plugin到处为一个单独的css文件
                 */
                use: [
                    // 默认vue中的样式是需要直接由vue-style-loader进行处理的,但是
                    // 这个loader是直接加上行内的,并不会导出为一个单独的CSS文件
                    // 所以这里使用了vue-loader官方文档提供的一种方法结合MiniCssExtractPlugin的loader
                    // 到处vue文件中的样式
                    process.env.NODE_ENV !== "production"?"vue-style-loader":MiniCssExtractPlugin.loader,
                    "css-loader",
                    {
                        loader: "postcss-loader",
                        options: {
                            //  通过postcss-loader的autoprefixer插件自动给需要兼容的css样式加前缀
                            plugins: [require("autoprefixer")]
                        }
                    },
                    "less-loader"
                ]
            },
            {
                test: /\.css$/,
                use: [
                    // 同时这也意味着无法处理js文件中导入的样式了
                    process.env.NODE_ENV !== "production"?"vue-style-loader":MiniCssExtractPlugin.loader,
                    {
                        loader: "postcss-loader",
                        options: {
                            //  通过postcss-loader的autoprefixer插件自动给需要兼容的css样式加前缀
                            plugins: [require("autoprefixer")]
                        }
                    },
                    "css-loader"
                ]
            },
            {
                // 正则表达式匹配entry指定的js文件中使用import或者require引入的文件
                // 这里匹配的是引入文件后缀名为.js的文件
                test: /\.js$/,
                use: {
                    // 指定要处理的loader
                    loader: "babel-loader",
                    // 可以给这个loader传递一些参数
                    // 在这里就相当于babel.config.js
                    options: {
                        presets: ["@babel/preset-env"],
                        plugins: ["@babel/plugin-transform-runtime"]
                    }
                },
                // 一定要配置这个exclude选项,禁止babel去转换node_modules模块下的代码
                // 不然就是一大堆奇奇怪怪的错误
                exclude: /node_modules/
            },
            {
                // 就这么简单
                // 请看less---> test注释  --> plugins需要引入一个插件
                test:/\.vue$/,
                loader:"vue-loader"
            }
        ]
    },

    // 所有插件都必须在plugins中new出来
    plugins: [
        new HtmlWebpackPlugin({
            // 指定需要打包的html文件
            template: "public/index.html",
            // 输出的文件
            filename: "index.html"
        }),
        new MiniCssExtractPlugin({
            // 会将所有的样式文件也合并到一个,这里需要指定一下对应样式文件的名称
            filename: "css/[name].css",
        }),
        // 一定要new这个插件
        new VueLoaderPlugin()
    ],

    // 这是webpack-dev-server的配置
    devServer: {
        // 绑定端口3000
        port: 3000,
        // 自动打开浏览器到指定网页
        open: true,
        // 热更新
        hot: true,
        // 代表网站根目录那样的,主目录是哪里
        // 这里是dist,所以会自动加载已经打包好的文件
        // 直接填你output中的path就行了
        contentBase: "dist"
    }
}

最后我们在进行快速搭建vue进行测试吧

npm i vue

修改main.js

import App from "./App.vue"
import Vue from "vue"

new Vue({
    render:h=>h(App)
}).$mount("#app");

index.html添加一个id为app的div,App.vue如下






然后最后直接

npm run dev

那么其实webpack中的内容远不止这些,还有好多比如说一些别名啊,性能优化啊,还有可以设置webpack-dev-server内置一些API啊,都可以在webpack.config.js中实现,那么其实呢,我也只能算带大家伙的先入门,那么关于以后的修行就看自己了

教程远没有结束,我还有不定期的更新一些插件啊,可能也会写写其他的配置,记得看最后的时间哦

有没有啥相对我说的或者交流的或者你对学习前端有困惑什么的,可以联系我哈群78484-->5854,偷偷告诉你楼主是自学的,并且不会英语哦

last update:2019年7月14日 16点09分

你可能感兴趣的:(webpack一文了解)