美文网首页大前端Web前端之路让前端飞
vue-cli中webpack把js文件引入index.html

vue-cli中webpack把js文件引入index.html

作者: 闫浩奇 | 来源:发表于2017-09-21 03:29 被阅读352次

    vue新手在用vue-cli写项目时候会发现,项目目录下index.html并没有通过<script></script>标签引入任何js。index.html如下:

    <!DOCTYPE html>
    <head>
    </meta charsets="utf-8">
    </meta name='viewport' content='width=device-width,user-scalable=no,scalable=1.0'>
    <head>
    <body>
      <div id="app"></div>
    <body>
    

    那么页面中的js文件是怎么引入的呢?具体过程,我们可以大概来看一下。

    我们先看下生产环境下的的项目文件是什么样的,执行npm run build,之后webpack会把项目打包到dist目录下,是这个样子:

    ├── index.html
    └── static
        ├── css
        │   ├── app.d41d8cd98f00b204e9800998ecf8427e.css
        │   └── app.d41d8cd98f00b204e9800998ecf8427e.css.map
        └── js
            ├── app.0171fcd8b30c24d68d55.js
            ├── app.0171fcd8b30c24d68d55.js.map
            ├── manifest.0c10b572fbaa20368a32.js
            ├── manifest.0c10b572fbaa20368a32.js.map
            ├── vendor.fbc8cfca4d796e6556b9.js
            └── vendor.fbc8cfca4d796e6556b9.js.map
    

    下面我们首先大概分析下,为什么执行npm run dev就会把文件打包到dist目录下呢?命令的设置是在package.json文件下的,打开package.json,找到scripts选项,可以看到npm run build实际执行的是node build/build.js

    ok,那我们看一下build.js是什么东东。打开build.js后在前面几行的位置会看见var webpack = require('webpack'),原来这个文件里面引入了webpack(webpack是在一开始npm install时候安装的),我们再全局搜索下webpack引入之后干了啥,可以看到后面有一句webpack(webpackConfig, function (err, stats) {...},快看,webpack被调用了!传入了一个webpackConfig和一个很长的函数,先不管这个函数是什么,我们看看这个webpackConfig是啥?全局搜索webpackConfig会看到上面有这样一句var webpackConfig = require ('./webpack.prod.conf'),你没猜错,我们还要继续看下webpack.prod.conf文件是啥。打开webpack.prod.conf.js,这个文件如果自己分析的话就很难再像刚才一样按图索骥找线索一步步捋了,我是我的有经验的朋友给我讲了一下(谢过陶神)然后我自己又百度查资料消化了一下才大概明白。这说明,有问题向别人请教非常重要,如果有懂得的人指点,会学的很快,知识就是用来分享的。这里我忍不住分享一篇文章自学只是一种学习方法

    扯远了,ok,come on!分析webpack.prod.conf.js,我们首先要认识一个插件webpack-html-plugin,这个plugin是帮做我们配置html文件中js文件的引入的,有了这个plugin我们就不用再用在html中加入<script src="..."></script>标签这么傻的方式引入js文件了。我们知道webpack的配置是通过module.exports导出一个node环境下全局的对象,我们可以看见文件中有一句var webpackConfig = merge(baseWebpackConfig, {...}merge函数?baceWebpackConfig参数?先看baceWebpackConfig是啥,全局搜索,找到这一句var webpackConfig = require(./webpack.bace.conf),然后我们看下wepack.bace.conf.js,其实已经见名知义了,打开文件惊喜的发现如下代码:

    module.exports = {
      entry: {
        app: './src/main.js'
      },
      output: {
        path: config.build.assetsRoot,
        filename: '[name].js',
        publicPath: process.env.NODE_ENV === 'production'
          ? config.build.assetsPublicPath
          : config.dev.assetsPublicPath
      },
    ...
    

    我们看到了./src/main.js,至于前面这个属性名app,我在项目文件中搜索entry.app啥都没有,搜索app然后出现一大堆app.use(),这个我就不再继续追踪分析了,心累~~~反正就是知道在这里我们找到了main.js。然后再回webpack.prod.conf.js找到刚刚让我们困惑的那句var webpackConfig = merge(baceWebpackConfing,{...}),那就很好理解了嘛,就是把这两个参数merge起来了嘛,不要和我说再研究下merge函数,见名知义(ps:真累了)!然后再把话题拉回刚刚提到的webpack-html-plugin插件,我们在webpack.prod.conf中全局搜索webpack-html-plugin找到HtmlWebpackPlugin,然后搜索HtmlWebpackPlugin,会发现:

    new HtmlWebpackPlugin({
          filename: process.env.NODE_ENV === 'testing'
            ? 'index.html'
            : config.build.index,
          template: 'index.html',
          inject: true,
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
            // more options:
            // https://github.com/kangax/html-minifier#options-quick-reference
          },
          // necessary to consistently work with multiple chunks via CommonsChunkPlugin
          chunksSortMode: 'dependency'
        }),
    

    这里不就有index.html吗?My God!而且会发现整个这段代码是一个数组的元素之一,这个数组是对象名为plugin的值,而plugin对象就是上面提到的merge函数的第二个参数(是个对象)的属性之一,果然不出所料。

    也就是说,通过这样一系列的复杂关系,main.js被自动引入到了index.html,那么这是我们的最终答案吗,no,我们来看下main.js

    import Vue from 'vue'
    import App from './App.vue'
    new Vue({
      el:'#app'
      templates:'<App></App>'
      components:{App}
    })
    

    main.js中引入了vue框架,并且实例化了vue,然后把引入的根组件App.vue绑在了id = app的元素上,index.html通过上述过程自动引入了main.js,而index.html中恰好有id = appdiv元素。再看根组件App.vue,这个组件又引入了其他组件,其他组件可能又会引入别的组件,每个组件中都由<template></template><style></style><script></script>三部分组成,其中的js又会形成复杂的依赖关系,这里不再继续探讨。

    最终,我们回到我们开始时候说的dist目录:

    ├── index.html
    └── static
        ├── css
        │   ├── app.d41d8cd98f00b204e9800998ecf8427e.css
        │   └── app.d41d8cd98f00b204e9800998ecf8427e.css.map
        └── js
            ├── app.0171fcd8b30c24d68d55.js
            ├── app.0171fcd8b30c24d68d55.js.map
            ├── manifest.0c10b572fbaa20368a32.js
            ├── manifest.0c10b572fbaa20368a32.js.map
            ├── vendor.fbc8cfca4d796e6556b9.js
            └── vendor.fbc8cfca4d796e6556b9.js.map
    

    main.js以及所有vue组件中的js都被打包成app.0171fcd8b30c24d68d55.jsapp.0171fcd8b30c24d68d55.js.map文件记录着各个js之间的位置关系,所有的vue组件的css文件都被打包为app.d41d8cd98f00b204e9800998ecf8427e.css,还有两个js文件应该是所有依赖的打包之后的文件吧,没有研究,最后index.html就是引入的这几个js和css文件。所有我们自己写的js和css就是经过这样复杂的过程被webpack打包的。

    其实我也不知道费这么大劲大概搞明白这些到底有啥用,只是一开始用vue-cli时候感觉很陌生,很多东西都很突兀,接受不了,当我慢慢去倒腾着大概的理解我想不明白的地方、一步步追踪最后得到自己满意答案之后,我就觉得我离vue-cli更近了,更了解了,不怎么怕它了,即使我知不知道这些,在写代码时候也基本用不上,但是就是心里的感觉不一样了。

    相关文章

      网友评论

      • 1285d54e2001:很詳細的講解,對於vue js 新手幫助很大
      • 始悔不悟:同感,之前对命令行有点抵触,学了下node自然很多😈

      本文标题:vue-cli中webpack把js文件引入index.html

      本文链接:https://www.haomeiwen.com/subject/jdwasxtx.html