webpack3.0小案例webpack初体验

1,670 阅读10分钟

写在前面

这篇文章是自己在整理webpack相关的东西时候突发奇想,想整理出一套由浅入深的博文以此鞭策自己学习,也希望能够帮助想学习webpack的同学,目前都是入门级别的,大佬请出门右转。

学习完本篇文章,我希望您能够掌握以下几点:

  • webpack是什么
  • webpack有什么有点
  • webpack.config.js配置项中,出口(entry)、入口(output)、插件(plugins)的基本作用和配置方法。
  • html-webpack-plugin、 clean-webpack-plugin 插件的作用和使用方法。

统一说明,本文中所用到的npm包管理工具均采用淘宝镜像(cnpm),原因你懂得。

webpack版本基于3.0版本,本文中具体是3.8.1版本。

什么是webpack

webpack是一个用以对现代Javascript应用程序模块打包工具,它和gulp、grunt的不同之处在于webpack提供了一整套前端模块化开发的解决法案;webpack把资源作为模块来处理,这里的资源不止于javascript,还包括html、css、图片、字体等等。

webpack的优点

  1. 代码分割(code splitting),在开发过程中,webpack允许我们将代码按照不同职能分割成不同模块进行开发,并且在加载中可以按需加载,减少加载时间。
  2. 插件化,webpack提供了丰富的插件接口,通过配置不同的插件,可以实现我们想要的效果,非常灵活。
  3. 装载机制,webpack中,我们可以通过提供的loaders预处理项目文件,包括js、css、html、image等。
  4. 高性能,webpack使用异步I/O流加载模块,并具有多个缓存级别,在渐进式编译中,速度表现很棒。
  5. 开发方便,weback提供sourceMap和sourceUrl,方便开发者定位调试,并且通过中间件可以实现项目的热更新,这个在开发中很有作用。

webpack使用

构建项目结构

1、初始化, 新建一个文件夹,取名叫webpackDemo,通过控制台或者git bash定位到当前文件下面,执行命令:

    npm init //淘宝镜像用 cnpm init

然后一路enter,初始化后,会在该文件夹下面生成一个package.json文件,然后,再次在命令行内执行:

    npm install //淘宝镜像用 cnpm install

2、项目结构搭建, 在webpackDemo文件夹下:

  • 新建src目录,用于存放开发相关的资源文件;
    • 在src目录下新建js、css、views等不同类型的文件夹,以此存放相对应的开发文件。
  • 新建dist目录,用于存放打包后生成的文件;
    • 和src目录下一样,新建js、css、views等文件夹,存放打包后的文件(案例中,先新建一个js文件夹,因为我们现在只用js来体验webpack)。
  • 新建index.html文件。
  • 新建webpack.config.js,这是webpack默认关于打包相关的配置文件。
  • 新建.babelrc文件,放置babel相关配置,和webpack.config.js一样,babel的配置文件名称,也是固定的,即:.babelrc

    注意: webpack默认会读取webpack.config.js 中的相关配置,如果更换其他名字,webpack默认是找不到配置信息的。(当然我们也可以去指定webpack读取的配置文件,在现阶段,我们暂不考虑);

    最终的项目结构如下:

    项目结构
    项目结构

初体验

1、代码编写,打开根目录下的index.html,引入webpack最后编译的的js文件,我么定义js名称叫做bundle.js。

    <!DOCTYPE html>
    <html lang="en">
    <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>webpack demo</title>
    </head>
    <body>
        <!-- 我们给最终编译出的js叫做bundle.js-->
        <script src="./dist/js/bundle.js"></script>
    </body>
    </html>

2、在src/js文件夹下面,新建app.js,作为webpack编译的入口文件,并添加一个方法,在控制台打印出hello world

    // app.js
    function Hello() {
        console.log('hello world')
    }
    Hello()

3、接下来,我们打开webpack.config.js,给webapck编译指定规则:

    // webpack.config.js
    var path = require('path');
    module.exports = {
    entry: path.resolve(__dirname, './src/js/app.js'),//指定webpack打包的入口是app.js
    output: {
        path: path.resolve(__dirname, './dist/js'),//指定打包后js文件放置的位置
        filename: 'bundle.js'//指定打包后的js名称,这个就是index.html最终引入的js的名称
        }
    }

1、配置路径用path.resolve()处理,是为了确保路径是从根目录开始绝对定位到指定位置,webpack3.0要求我们在配置路径相关的时候使用绝对路径;
2、path模块是nodejs内置的处理路径相关的模块。

现在让我们打开命令行,执行webpack编译

    //如果还未安装webpack,则先执行安装
    cnpm i webpack --save-dev

    // 安装完成后执行编译
    webpack

编译执行完成后,控制台输出以下则表示执行成功。

webpack 编译
webpack 编译

此时查看dist/js目录,会发现新增了一个bundle.js的文件,在浏览器中打开index.html,再打开控制台,成功输出hello world。

webpack 编译
webpack 编译

看到这里,估计有人要打人了,就这玩意有啥用,浪费我青春!我要输出的hello world要你这么麻烦干啥。额!骚年,先放下你手上的砖头,有话好好说。

大名鼎鼎的webpack当然不止这就完了,接下来,让我们一步一步真正开始认识webpack。

webpack 编译
webpack 编译

webpack配置---生成带hash值的js文件

现在,我们来看一下webpack配置文件中的output选项的相关配置,细心的你也许发现,我们最终生成的的bundle.js是我们设定好的,每次打包后生成的名字是不会改变的,但是在实际项目中,为了确保代码更改前后无冲突以及版本回退等一系列问题,每次打包后的包文件,我们会给他打上一个独一无二的标记,用以区分版本,这又是怎么实现的呢?

实际上,webpack在打包编译的时候,会把不同模块的代码分别指定一个chunkhash值,最后整体打包后的js会生成一个hash值 (需要注意chunkhash和hash是不一样的),我们只需要在output配置项中给filename属性一个填写hash的占位符,这样在每次编译的时候,就会生成带有hash值得js文件:

  var path = require('path')
  module.exports = {
    entry: path.resolve(__dirname, './src/js/app.js'),
    output: {
        path: path.resolve(__dirname, './dist/js'),
        filename: 'bundle-[hash].js'//[hash]为编译时填写hash的占位符,也可以填写chunkhash等
    }
  }

再次执行编译,我们会发现,新生成的文件已经带有hash值了:

webpack 编译
webpack 编译

webpack配置---根据模板动态生成Html

上面我们已经动态生成了带有不同hash值得js了,那么问题又来了,既然每次生成的js文件都不一样,我们如何去加载生成的js呢,要知道,在index.html里面,我们写的是bundle.js啊!

为了解决这个问题,我们就想,如果每次webpack打包编译后自动将生成的js注入到我们的index.html模板中,这样我们就不用在我们的index.html中手动添加bundle.js了,不就解决了这个问题么。

实际上!这种思想正是webpack为我们提供的解决方案-- html-webpack-plugin

首先,我们通过命令行安装这个插件

    cnpm install html-webpack-plugin --save-dev

html-webpack-plugin
html-webpack-plugin

然后,我们在配置文件里新增对html-webpack-plugin的相关配置

    var path = require('path');
    //引入html-webpack-plugin模块
    var htmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
        entry: path.resolve(__dirname, './src/js/app.js'),
        output: {
            path: path.resolve(__dirname, './dist/js'),
            filename: 'bundle-[hash].js'
        },
        //初始化插件
        plugins:[
            new htmlWebpackPlugin({
                template:'index.html',//定义插件读取的模板文件是根目录下的index.html
                filename:'index.html'//定义通过模板文件新生成的页面名称
            })
        ]
    }

在配置文件中,我们新增了plugins这个配置属性,并初始化html-webpack-plugin插件,现在我们去index.html中删除js的引用。

    <!DOCTYPE html>
    <html lang="en">
    <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>webpack demo</title>
    </head>
    <body>
       <!--  <script src="./dist/js/bundle.js"></script>-->
    </body>
    </html>

再次执行webpack命令,编译成功后!再看看我们的dist目录下,果然生成了index.html。

html-webpack-plugin
html-webpack-plugin

提醒一

html-webpack-plugin插件运行的时候,需要在项目安装webpack,如果是全局安装的webpack,在此处运行会报错:Cannot find module 'webpack/lib/node/NodeTemplatePlugin'

html-webpack-plugin
html-webpack-plugin

html-webpack-plugin
html-webpack-plugin

解决办法就是在本地安装webpack,定位到项目的根目录下执行以下命令即可。

    cnpm install webpack

提醒二

细心的你可能又发现,生成的index.html也在dist/js文件夹下面,这和我们想要的结果不一样,因为我们想要在dist文件夹下把html、js以及后面的css都分开来,为了解决这个问题,我们须将配置文件的output选项更改一下:

    var path = require('path')
    var htmlWebpackPlugin = require('html-webpack-plugin')
    module.exports = {
        entry: path.resolve(__dirname, './src/js/app.js'),
        output: {
            // path: path.resolve(__dirname, './dist/js'),
            path: path.resolve(__dirname, './dist'),//将输出的路径定位到dist一级就好,然后再filename配置项中,指定二级目录。
            //filename: 'bundle-[hash].js'
            filename: 'js/bundle-[hash].js'
        },
        plugins: [
            new htmlWebpackPlugin({
                template: 'index.html',
                filename:'index.html'
            })
        ]
    }

在配置中,我们将output中的path路径指定到dist一级就好,至于生成的js路径,我们就将js放置在filename选项下,配置完成后,我们再次在命令行执行"webpack"命令,最终发现,dist目录下新生成了index.html页面,而js,则依然在js文件夹下生成。

html-webpack-plugin
html-webpack-plugin

webpack配置---清除dist文件夹下面的重复文件

到目前为止,我们的案例可以动态的生成带有自己hash命名的js文件,但是我们发现文件在一直增加,新生成编译文件之前并没有删除上一次编译的文件,这会让项目原来越大。为了解决这个问题,我们需要再次引入一个插件---clean-webpack-plugin

老规矩,首先是安装,在命令行执行:

    cnpm install clean-webpack-plugin --save-dev

然后在配置文件中引入插件并实例化

    var path = require('path');
    var htmlWebpackPlugin = require('html-webpack-plugin');
    //引入插件模块
    var cleanWebpackPlugin = require('clean-webpack-plugin');
    module.exports = {
        entry: path.resolve(__dirname, './src/js/app.js'),
        output: {
            path: path.resolve(__dirname, './dist'),
            filename: 'js/bundle-[hash].js'
        },
        plugins: [
            new htmlWebpackPlugin({
                template: 'index.html'
            }),
            //初始化插件配置项
            new cleanWebpackPlugin(
                ['dist'], //匹配要删除的文件,这里则指定每次对dist文件夹进行清理
                {
                    root: __dirname,//指定插件根目录位置
                    verbose: true, //开启在控制台输出信息
                    dry: false //启用删除文件
                }
            )
        ]
    }

在配置中,我们将引入的clean-webpack-plugin实例化,并设置了要删除文件的目录和一些显示设置,再次在命令行执行"webpack"命令,发现之前的文件被删除了,只剩下最新生成的相关文件。

clean-webpack-plugin
clean-webpack-plugin
;

写在最后

这一节,我们向大家初步介绍了webpack的使用,并且从头开始搭建了一个webpack运行的编译环境,初次体验了一下webpack,当然,webpack的功能远远不止于此,它的最重要的功能loader我们还没开始,目前笔者所展示的这些,只是webpack很小很小的一部分。

再次提醒读者盆友,读完本篇文章您应该了解以下内容:

  • webpack是什么
  • webpack有什么有点
  • webpack.config.js配置项中,出口(entry)、入口(output)、插件(plugins)的作用和基本配置方法。
  • html-webpack-plugin、 clean-webpack-plugin 插件的作用和使用方法。

下一节,我们将在此基础上学习webpack的加载器用法,包括babel编译es6、css预处理、autoprefixer用法、css与js文件分割等,欢迎大家提出宝贵意见,一起学习。

这是前端最好的时代,也是前端最坏的时代,前端不止,学习不停,愿各位读者努力向前,早日成为前端高手。

pix
pix