WebPack基础教程

手动构建Webpack开发环境
WebPack基础教程
Webpack开发环境配置
webpack+sass+babel+postcss配置
Webpack多页面配置

WebPack基础教程

WebPack是目录前端用于构建自动化开发的一款非常流行的工具,与之前的gulp和grunt功能非常相似,它们都是一款通过JavaScript来构建Web网站的自动化工具!

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

我们可以通过下面的一张图来完理解这一部分的功能

在这里插入图片描述

webpack可以全一切变得都非常简单,它提倡模块化进行开发,拼提供通过工具的操作简化和提高前端开发工作

入门

WebPack是基于NodeJs平台运行的,所以,在合作Webpack之前,请先保证自己的开发环境下有NodeJs的运行环境

  1. 安装Webpack

    目前我们所使用的Webpack的版本为webpack3的版本,最新的版本为webpak4的版本,因最新版本对一些插件不支持,并有部分不稳定的情况,我们此处以webpack3为版本进行讲解

    $ cnpm install webpack@3 -g
    

    说明:上面的代码是全局安装webpack3的版本

  2. 编写JS代码,通过webpack来进行打包处理

在这里插入图片描述

我们在上面的代码当中,创建了一个app.js和bar.js 然后在app.js中通过ES6的模块化开发,引入了这个文件

正常情况下,我们是不可能在浏览器中使用export与import等这些关键字的,现在,我们可以在这里通过webpack来打印处理一下

$ webpack app.js bundle.js

说明:好面的代码是将app.js通过webpack打包以后,翻译成bundle.js,打包完成以后,我们就可以在浏览器中正常使用这个JS文件了

  1. 引入文件,查看效果

在这里插入图片描述

通过上面的入门,我们发现,其实,使用Webpack并不是很验,至少我们可以得出以后结论

  • webpack可以将es6的代码转换成我们浏览器使用的代码(正常情况下,es6的代码需要在nodejs环境下面才能够运行)
  • 我们通过webpack可以在进行模块化开发,同时,在模块化开发的过程当中,把这些模块化的代码运行于浏览器(以前的模块化开发,我们只是针对Nodejs的平台)

在这里,我们的Nodejs的一切比较良好的模块化开发特性,以及ES6的一些高效语法就都可以在这里进行使用了

WebPack.config.js的配置

在上面的入门代码里面,我们知道,如果要把我们的代码进行打包处理,则需要手动的去执行一条命令,但是这样操作非常麻烦 ,我们不可能每次更改代码以后都去手动的执行一次命令,这个时候,我们可以通过一个配置文件,来配置我们的Webpack操作

Webpack的配置文件,我们一般命名为webpack.config.js这个文件,在这个文件里面,有四大部分,如下:

  • 入口(entry)
  • 出口(output)
  • loader
  • 插件(plugins)
入口(entry)

首先,我们先在项目的根目录下面,创建一个webpack.config.js的文件,然后打开文件,编写如下代码

module.exports = {
  entry: './src/app.js'
};

说明:上面的./src/app.js代表的就是这个程序的入口文件

出口(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件。你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

  const path = require('path');
 
module.exports = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  }
};

在上面的代码中,我们通过 output.filenameoutput.path 属性,来告诉 webpack bundle 的名称,以及我们想要生成到哪里。

就像之前的入门里面,我们使用webpack app.js bundle.js 一样,前面是入口文件,后面是出口文件

loader

loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

例如,我可以让webpack来处理scss的预处理CSS文件,也可以让webpack来处理vue的文件,这都是webpack所具务的功能,但是,webpack如果想要使用这些功能,必须要使用第三方的模块,而这些第三方的模块,我们就叫做loader

注意,loader 能够 import 导入任何类型的模块(例如 .css 文件),这是 webpack 特有的功能,其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是有很必要的,因为这可以使开发人员创建出更准确的依赖关系图。

在配置loader的时候,里面有两个必填属性,一个是test,一个是use属性:

  1. test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
  2. use 属性,表示进行转换时,应该使用哪个 loader。
const path = require('path');
const config = {
  entry: './src/app.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      { test: /\.scss/, use: 'sass-loader' }
    ]
  }
};
module.exports = config;

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:testuse。这告诉 webpack 编译器,如下信息:

“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 ‘.scss’ 的路径」时,在你对它打包之前,先使用 sass-loader 转换一下。”

在此处说明一下,webpack的loader必须配置在module.rules这个属性里面!

插件 plugins

插件在此得先不作说明,后期案例具体说明

Webpack与Babel的结合

我们刚刚说过一件事情,就是我们在使用webpack的时候,可以将我们的es6代码的模块化运用得非常好,但是,有些时候,浏览器必不能识别所有的es6代码,这个时候,我们就需要使用一个第三方模块,来处理我们的es6代码,而这个模块就是babel

Babel是一款非常浏览的代码翻译工具,无论是现在的ES6,还是Vue或React,这些大名鼎鼎的框架都是要基于Babel的,如果脱离了Babel,这些框架运行起来会非常困难

首先,我们要知道 Babel的第三方模块如果去使用。在Babel的中文官网当中,我们可以找到babel在webpack中的配置(在此处说明一下,babel这个第三方模块不只是运行在webpack中,还可以运行在其它的平台),具体使用步骤如下:

  1. 安装

    $ cnpm install --save-dev babel-loader babel-core
    
  2. 通过config进行配置

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

    说明:上面的代码的意思就是告诉webpack,如果碰到.js的文件,就使用第三方的模块babel-loader来进行处理一下,但是并不是所有的js文件都要处理,在node_modules这里面的文件就不要处理了

  3. 配置代码的处理方式

    我们刚刚都说过了,我们的babel是一个代码翻译工具,它会把我们的代码翻译成我们浏览器认识的语言,可是,我们总要告诉babel我们所使用的语言到底是什么语言吧,这个时候,我们就需要添加一个babel的专用配置文件

    我们需要在项目的根目录下面创建一个.babelrc这个文件,然后在这个文件当中,配置如下信息:

    {
      "presets": ["env"]
    }
    

    说明:我们看到了一个presets这个选项后面根着的是env,这个env代表的是根据当前的运行环境自动选择编译项,而这个运行环境是什么呢,babel也不知道,所以,我们要告诉babel,这个时候,我们找到项目的package.json文件,配置一下当前的运行环境

    {
      "name": "webpack04",
      "version": "1.0.0",
      "description": "webpack手动配置项",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack --config webpack.config.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.4",
        "webpack": "^3.11.0"
      },
      "browserslist": [
        "defaults",
        "not ie < 11",
        "last 2 versions",
        "> 1%",
        "iOS 7",
        "last 3 iOS versions"
      ]
    }
    

    说明:在上面的代码当中,我们看到了一个配置项browerslist这个,在这里,我们配置了一些信息,其中的信息 是默认配置,然后非IE11等信息

  4. 配置代码的stage环境

    现在的ECMASCript标准已经发展到es8了,所以,我们在书写JS代码的时候,可以使用一些比较新的特性,例如我们的异步处理当中的asyncawait这些方法。如果要让我们的浏览器支持async与await这些方法,仅仅是通过webpack和babel的一些常规处理方法是不行的,我们需要使用babel-preset-stage-0babel-polyfill这两个插件

    说明:Babel 包含一个可自定义 regenerator runtimecore-jspolyfill .

    它会仿效一个完整的 ES2015+ 环境,并意图运行于一个应用中而不是一个库/工具。这个 polyfill 会在使用 babel-node 时自动加载。

    这意味着你可以使用新的内置对象比如 Promise 或者 Map, 静态方法比如 Array.from 或者 Object.assign, 实例方法比如 Array.prototype.includes 和生成器函数(提供给你使用 regenerator 插件)。为了达到这一点, polyfill 添加到了全局范围,就像原生类型比如 String 一样。

    • 第一步:先安装babel-preset-stage-0babel-polyfill

      $ cnpm install babel-preset-stage-0 babel-polyfill --save-dev
      
    • 第二步:修改webpack.config.js中的entry入口

      var config={
          entry: ["babel-polyfill", path.join(__dirname, "./src/main.js")]
          //....
      }
      module.exports=config;
      
    • 第三步:修改babel的配置文件

      .babelrc的配置文件中,修改成如下:

      {
          "presets": [
              "env", "stage-0"
          ]
      }
      

    通过上面的配置以后,我们就可以正常的使用ES6里面新特性了

webpack生成编译文件

当我们配置好webpack的配置文件以后,所以的操作我们就都可以交给webpack来处理了,这个时候,我们在进行编译的过程当中,要让webpack来使用我们的配置文件,这个时候,需要执行如下命令

$ webpack --config webpack.config.js

命令执行成功以后,就会在指定的目录生成我们的目录文件,这个时候,我们可以把这条命令写在package.json这个文件里面

在package.json的文件里面,我们在scripts这个节点里面,添加如下代码:

{
  "name": "webpack04",
  "version": "1.0.0",
  "description": "webpack手动配置项",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.4",
    "webpack": "^3.11.0"
  },
  "browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
  ]
}

上面的build就是我们添加的自定义命令,添加自定义完成以后,我们就可以在控制台输入 npm run build 来执行上面的命令,最终会执行我们的webpack的打包操作

webpack开发环境与生产环境

我们在使用webpack进行打包配置的时候,我们不可能一直去执行生成的操作,然后去把生成的bundle.js这个文件引入到我们的HTML文件当中,这个的开发非常麻烦,也非常繁琐,这个时候,Webpack本身也考虑到这个问题

官方针对这种情况推出了一个小型的基于express的迷你http服务器,可以让我们开发的网页运行在http的服务器下面,然后做到实时编写,实时编译,这个时候,效果就会非常高!这一种高效的环境,我们叫做webpack的开发环境

Webpack的开发环境当中的http服务器依赖于webpack-dev-server,从名字当中我们可以看出这是webpack的开发服务器,接下来的过程里面,我们来了解一下如何学配置webpack的开发环境

  1. 首先,我们需要安装webpack-dev-server

    $ cnpm install webpack-dev-server@2 --save-dev
    

    说明:上面的webpack-dev-server我们使用的是2的版本,目前最新版为3

  2. 在package.json的文件当中,添加开发环境的启动命令!

    我们会在package.json的scripts的脚本下面添加如下命令

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

    说明:上面的dev就是我们配置的启动名称,后面的代码就是启动命令

    通过上面的dev代码,我们会发现,这个时候的打包命令由webpack变成了webpack-dev-server,这个时候,我们会在这个地方以webpack-dev-server的方式来打包,但是,我们需要弄清楚一点,这个时候,我们使用的配置文件都是webpack.config.js这个文件,而我们的build命令与dev的命令又是不一样的,这个时候,我们就需要在webpack.config.js的文件当中做出一些区分,具体代码如下所示:

    const path = require('path');
    const ExtractPlugin = require('extract-text-webpack-plugin');
    const webpack = require('webpack');
    const HTMLPlugin = require("html-webpack-plugin");
    
    //根据启动参数去判断是否等于development,如果是就是开发环境,如果不是,就是生产环境
    var isDev = process.env.NODE_ENV === "development" ? true : false;
    
    var config = {
        entry: ["babel-polyfill", path.join(__dirname, "./src/main.js")],
        output: {
            path: path.join(__dirname, "./dist"),
            filename: "bundle.js"
        },
        module: {
            rules: [{
                    test: /\.js$/,
                    use: ["babel-loader"],
                    include: path.join(__dirname, "./src")
                },
                {
                    test: /\.css$/,
                    use: [
                        "style-loader",
                        "css-loader"
                    ]
                },
                {
                    test: /\.scss$/,
                    use: [
                        "style-loader",
                        "css-loader",
                        {
                            loader: "postcss-loader",
                            options: {
                                config: {
                                    path: path.join(__dirname, "./postcss.config.js")
                                }
                            }
                        },
                        "sass-loader"
                    ]
                },
                {
                    test: /\.(jpg|jpeg|png|gif|svg|bmp)$/,
                    use: [{
                        loader: "url-loader",
                        options: {
                            limit: 1000,
                            name: "[name]-aaa.[ext]"
                        }
                    }]
                }
            ]
        },
        plugins: [
            new HTMLPlugin({
                template: "index.html",  //模板文件的位置
                inject: true
            })
        ]
    }
    if (isDev) {
        config.devServer = {
            host: "0.0.0.0",
            port: 8888,
            overlay: {
                error: true
            }
        }
    } 
    module.exports = config;
    

    说明:在上面的代码当中,我们看到我们使用了一个叫process.env.NODE_ENV的文件来判断当前的环境是否是开发环境,这个时候,我们如何去区分他们的环境呢?

    我们刚刚在package.json的文件当中,通过"build"与"dev"的两个命令来区分,但是,这只是启动方式改变了,后面的配置文件还是同一个,为了区分这个环境,我们需要一个第三方的模块 cross-env,这个模块可以在启动命令的前面添加启动参数,这个启动参数会传递到nodejs的运行环境当中

    现在,我们安装cross-env以区分不同的启动方式

    $ cnpm install cross-env --save-dev
    

    安装完成以后,我们把上面的scripts中的启动命令改成如下:

    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
        "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
    }
    

    在上面的代码里面, 我们分别在启动命令前面用cross-env来区分NODE_ENV到底是production还是development

    区分了环境以后,我们用了一个变量isDev来判断,如果是开发环境,我们在后面配置了一个devServer那么,我们可以在里面配置它的服务器地址,服务器端口,服务器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值