webpack

6 篇文章 0 订阅

1.webpack官方文档

2.为什么要用webpack

让我们从一个html页面说起,下面的代码可以看到,我在html页面中通过script标签引入了3个JavaScript文件a.jsb.jsc.js,每个文件中分别定义了一个函数并导出(export)给外部用。并且它们之间有一定的依赖关系,c.js依赖于b.jsb.js依赖于a.js

// index.html
<!doctype html>
<html>
  <head><link href="main.css" rel="stylesheet"></head>
  <body>
    <div>hello world</div>
    <script type="text/javascript" src="a.js"></script>
    <script type="text/javascript" src="b.js"></script>
    <script type="text/javascript" src="c.js"></script>
  </body>
</html>

因为有3个js文件,所以浏览器需要发送三次http 请求来获取这三个文件,然后依次执行其中的代码,如果其中有一个文件因为网络问题而延误了时间,那么整个页面的显示也会被延误。3个文件还好,而当我们的项目逐渐变大,有几十个到上百个JavaScript文件的时候,那问题会更严重,不但有延迟问题,还会遇到很难维护的问题 — 想想如何维护上百个文件的依赖关系?

这时候你会想,是不是我把所有JavaScript文件合成一个文件就好了呢?没错,我们确实可以这样做,这样就减少了http请求数量,让我们的页面加载和显示更快。不过这个合并的阶段是在开发完成之后才进行的,也就是说开发阶段我仍然是有a.jsb.jsc.js等等这些文件的,这样才好开发和维护,因为如果开发阶段就合并的话,就相当于我基于一个可能上万行的文件进行开发,这样的代码是没法维护的。

在开发后完成的这个合并的过程就是打包,这样你就明白为什么要打包了吧。webpack在打包过程中,会分析各个文件之间的依赖关系,然后生成一个依赖图并用文件的形式保存下来,未来浏览器运行代码的时候就可以读取这个文件,就知道了各个代码块之间的关联以及如何调用了。
在这里插入图片描述

3.webpack安装

  1. 安装webpack,运行npm i webpack -g全局安装webpack或在项目根目录中运行npm i webpack --save-dev
  2. 接着全局安装 webpack-cli(此工具用于在命令行中运行 webpack)npm i webpack-cli -g

4.初步使用webpack打包构建项目

  1. 运行npm init初始化项目
  2. 创建项目目录
  • dist (文件夹是编译后或者压缩后的代码,终发布版本的代码)
  • src (文件夹是源码文件)
    • css
    • img
    • js
    • index.html (首页)
    • index.js (js的入口文件)
    • package.json (注:该文件不能写注释,只要是json都不能加,不然运行webpack会报错)
    • webpack.config.js
  1. 安装要其他依赖库,此处以jquery为例,在项目根目录运行npm i jquery -s

  2. 在index.js中导入依赖库

    //	import 用变量接收 from '导入包的名称'
    // 如果要通过路径的形式,去引入 node_modules 中相关的文件,可以直接省略 路径前面的 node_modules 这一层目录,直接写 包的名称,然后后面跟上具体的文件路径
    // 不写 node_modules 这一层目录 ,默认 就会去 node_modules 中查找,如下为引入bootstrap的css样式的方式
    //import 'bootstrap/dist/css/bootstrap.css'
    import $ from 'jquery'
    
    $(function(){
        $('li:odd').css('backgroundColor','red')
    })
    
  3. 使用webpack对index.js进行打包
    原因:浏览器不认识import这种高级语法,需要用webpack进行处理,将其转换成哼浏览器能识别的语法
    (1)创建webpack.config.js
    (2)在webpack.config.js中配置打包信息

    const path = require('path');
    
    module.exports = {
      entry: './src/index.js',  //打包的入口文件
      output: {   //打包完的输入文件
        path: path.resolve(__dirname, 'dist'),    //打包输出的文件目录
        filename: 'bundle.js'     //打包输出的文件名
      }
    };  
    

    (3)运行webpack初始化项目,会将index.js打包输出到dist中的bundle.js;
    (4)在index.js中引入bundle.js

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script src="../dist/bundle.js"></script>
    <body> 
        <ul>
            <li>d</li>
            <li>d</li>
            <li>d</li>
            <li>d</li>
            <li>d</li>
        </ul>
    </body>
    </html>
    

5.webpack-dev-server——在内存中自动打包编译bundle.js插件

  1. 运行npm i webpack-dev-server -D
    在这里插入图片描述
    然后会报以上错误,提示需要在本地安装webpack,此时已经全局安装过webpack了,也就是说如果想要使用webpack-dev-server这个工具,就必须在本地安装webpacknpm i webpack -D

  2. 在package.json中有的scripts配置脚本命令
    由于项目中的 webpack-dev-server是本地安装的,所以无法把它当做脚本命令在终端直接运行(只有那些安装到全局-g的工具,才能在终端上正常运行),所以想要运行我们需要在package.json中有的scripts配置脚本命令,scripts是用于指定脚本命令,供npm直接调用。

     "scripts": {
        "start": "webpack-dev-server"
      }
    
  3. 运行npm run start
    start是运行命令名称,在配置中用什么名称,就需要用npm run 名字来运行,可在配置中更换运行指令的名称。
    运行成功,显示如下,可通过ctr并点击http://localhost:8080/进入文件目录
    在这里插入图片描述
    该文件目录中dist并没有生成bundle.js,而是直接托管到了电脑的内存中,所以在根目录中找不到bundle.js,这样做的优点是速度快,且不会消耗我们的磁盘。
    在这里插入图片描述
    由于之前我们引入的是磁盘上的路径,这里应该跟目录的bundle.js,并且访问形式必须是http://localhost:8080/src/,而不能是本地路径

    <script src="/bundle.js"></script>
    
  4. webpack-dev-server的常用配置
    第一种配置方法:在package.json中的scripts中添加

     "scripts": {
    		"start": "webpack-dev-server  --port 3000 --contentBase src --hot"
    		}
    

    (1)–open 保存自动打开(这个我一般不开,会有174的bug,不要启用即可)
    (2)–port 3000 设置端口号
    (3)–contentBase src 设置默认打开的根路径
    (4)–hot 只更新修改的代码,而不是重新生成bundle.js,还能实现浏览器的无刷新重载,即代码改变了不需要刷新浏览器也能重载。
    第二种配置方法:在webpack.config.js的devServer中配置

    	 devServer: { // 这是配置 webpack-dev-server 的第二种形式
    	    port: 3000, // 设置启动时候的运行端口
    	    contentBase: 'src', // 指定托管的根目录
    	    hot: true // 启用热更新 的 第1步
    	  }
    

6.html-webpack-plugin ——在内存中自动打包编译html页面插件

  • 作用:(1)创建一个在内存中生成的html页面的插件(2) 自动把打包好的 bundle.js 追加到页面中去,当使用 html-webpack-plugin 之后,我们不再需要手动处理 bundle.js 的引用路径了,因为这个插件,已经帮我们自动创建了一个合适的 script , 并且,引用了正确的路径
  • 步骤:
    1. 运行npm i html-webpack-plugin -D安装插件;

    2. 在webpack.config.js中导入该插件

      const htmlWebpackPlugin = require('html-webpack-plugin')
      
    3. 在webpack.config.js中的plugins中配置该插件(只要是插件都要在plugins中配置)
      配置参数:
      template——指定模板页面,将来会根据指定的页面路径,去生成内存中的页面
      filename——指定生成的页面的名称

       plugins: [ // 配置插件的节点
          new htmlWebpackPlugin({ // 创建html-webpack-plugin插件
            template: path.join(__dirname, './src/index.html'), 
            filename: 'index.html' 
          })
        ]
      
    4.运行npm run start

7.style-loader、css-loader ——打包处理css第三方模块加载器

  • 作用:webpack默认只能打包处理 JS 类型的文件(打包import导入的文件),无法处理其它的非 JS 类型的文件;如果要处理非JS类型的文件,我们需要手动安装一些第三方 loader 加载器;

  • webpack 处理第三方文件类型的过程:

    1. 如果是js文件可以直接打包,如果是非js文件,就会拿到后缀名去webpack.config.js配置文件中的module中的rules内,查找有没有对应的第三方 loader 匹配规则
    2. 如果能找到对应的规则, 就会调用 对应的 loader 处理 这种文件类型,如果找不到就会报错;
    3. 在调用loader 的时候,是从后往前调用的,即{ test: /\.css$/, use: ['style-loader', 'css-loader'] }是先调用css-loader再调用style-loader;
    4. 当最后的一个 loader 调用完毕,会把 处理的结果,直接交给 webpack 进行 打包合并,最终输出到 bundle.js 中去
  • 步骤:

    1. 运行npm i style-loader css-loader -D安装插件;
    2. webpack.config.js 里配置规则
      webpack.config.js里面新增一个 配置节点module, 它是一个对象,用于配置所有第三方模块加载器;module 对象有个 rules 属性,这个 rules 属性是个 数组,该数组中存放了所有第三方文件的匹配和处理规则;
       module: { // 这个节点,用于配置 所有 第三方模块 加载器,第三方模块就是指用import导入的文件
          rules: [ // 所有第三方模块的 匹配规则
            { test: /\.css$/, use: ['style-loader', 'css-loader'] }, //  配置处理 .css 文件的第三方loader 规则
            { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, //配置处理 .less 文件的第三方 loader 规则
            { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, // 配置处理 .scss 文件的 第三方 loader 规则
          ]
        }
      
    3. 在js入口文件的main.js文件中引入css
      	import './css/index.css'
      	import './css/index.less'
      	import './css/index.scss'
      
  • 配置less、sass的loader案例:

    1. 运行npm i less-loader -D安装插件;
      控制面板上会提示“
      peerDependencies WARNING less-loader@* requires a peer of less@^2.3.1 || ^3.0.0 but none was installedr”,表示该loader内部依赖于less,因此要再安装less。因为是内部依赖所以不需要在配置文件中定义。在这里插入图片描述
    2. 运行npm i less -D
    3. webpack.config.js 里配置规则
      由于less也是样式,因此必须调用’style-loader’和’css-loader’,安装方法如上。
      	 module: { 
      	    rules: [ 
      	      { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, 
      	    ]
      	  }
      
      先调用less-loader把他处理成普通样式,然后给css-loader、style-loader调用处理,配置sass-loader同理。

8.url-loader——处理图片文件地址和字体图标文件地址

  • 作用:处理url地址。webpack无法处理css文件中的url地址,不管是图片还是字体图标地址库,只要是url地址都处理不了。因此只要css用到url或需要用到字体图标,都应该引入url-loader
  • 步骤:
  1. 通过css文件在html中加入图片,从入口文件main.js中引入css,运行webpack
    html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <div class="box" ></div>
        <div class="box2" ></div>
    </body>
    </html>
    

    css:

    .box{
      width: 220px;
      height: 120px;
      background: url('../images/22.jpg');
    }
    .box2{
      width: 220px;
      height: 120px;
      background: url('../images2/22.jpg');
    }
    

    会报错,因为webpack默认无法处理url地址。因此需要借助于url-loader
    在这里插入图片描述

  2. 运行cnpm i url-loader file-loader -D,url-loader依赖于file-loader。

  3. 在webpack.config.js中,添加如下module规则:
    loader传参的方式和url地址一样,都是?传参,处理方式如下

    module: {
    				   rules: [
    				        // { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader' },
    				       { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7631&name=[hash:8]-[name].[ext]' }, // 处理图片文件的 loader 
    				       { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' }, // 处理 字体文件的 loader 
    				    ]
    			  }
    

    如果要在template中引用src,则要加上如下配置

    rules: [ 
      { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: [{
        loader:'url-loader?limit=3000&name=[name].[ext]',
        options:{
          esModule:false
        }
      }] }
    ]
    

    参数的定义:

    (1)limit ——给定的值,是图片的大小,单位是 byte, 如果我们引用的图片,大于或等于给定的 limit值,则不会被转为base64格式的字符串, 如果图片小于给定的 limit 值,则会被转为 base64的字符串。
    如果为使用limit参数,或图片小于limit给定值时,图片会被生成base64如下:
    在这里插入图片描述
    如果设置了limit参数,且图片大于等于limit给定值,如果没有设置name参数,name会自动生成一个图片路径地址,该地址名称不是我们实际命名的图片名称,如下:
    在这里插入图片描述
    (2)name=[name].[ext]——如果想要生成的图片名称就是我们实际命名的名称,则要加上该参数,,若没有这句,则会自动生成一个其他名的路径地址。
    加上该参数后的生成的图片地址
    在这里插入图片描述
    (3)[hash:8]——因为每张图片的hash值都不一样,所以前面用hash链接,以防webpack帮我们自动生成图片时,不同路径的同名图片发生覆盖的情况,hash值是32位的,这里取前8位

9.bable-loader——处理更高级的ES6语法或者ES7语法

  • 作用:
    如今 ES6 语法在开发中已经非常普及,甚至也有许多开发人员用上了 ES7 或 ES8 语法。然而,浏览器对这些高级语法的支持性并不是非常好。因此为了让我们的新语法能在浏览器中都能顺利运行,Babel 应运而生。
    Babel是一个JavaScript编译器,能够让我们放心的使用新一代JS语法。比如我们的箭头函数、 static语法:
    () => console.log('hello babel')
    
    class Person {
        static info = { name: 'zs', age: 20 }
    }
    
    如若没有使用,则会报错。
    在这里插入图片描述
  • 步骤:
    1. 运行cnpm i babel-core babel-loader babel-plugin-transform-runtime -Dcnpm i babel-preset-env babel-preset-stage-0 -D
      第一个包相当于转换器,把高级语法转换成低级语法,第二包preset语法相当于字典,提供高级语法和低级语法之间的对应关系,能让webpack知道怎么把高级语法转换成低级语法,二者缺一不可。
      注:安装过程中若出现以下错误requires a peer of @babel/core@^7.0.0 but none was installed,则表示babel-loader的包太高级了,于其他插件不匹配,这时候可以先卸载cnpm un babel-loader,然后运行cnpm i babel-loader@7 -D,根据提示下载对应的版本,@后面为版本号。几个解决这个错误。
      在这里插入图片描述

    2. 在webpack.config.js中添加配置

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

      在配置 babel 的 loader规则的时候,必须 把 node_modules 目录,通过 exclude 选项排除掉,因为如果不排除node_modules,则Babel会把node_modules 中所有的 第三方JS文件,都打包编译,这样,会非常消耗CPU,同时,打包速度非常慢。最终,Babel 把 所有 node_modules 中的JS转换完毕了,但是,项目也无法正常运行!

    3. 在项目的 根目录中,创建 .babelrc 的Babel 配置文件
      (1)这个配置文件属于JSON格式,所以,在写 .babelrc 配置的时候,必须符合JSON语法规范: 不能写注释,字符串必须用双引号。
      (2)要配置带有preset和plugin的插件,要在配置项数组里面填写插件的名称,插件名称要去掉preset和plugin前缀。babel-plugin-transform-runtimebabel-preset-envbabel-preset-stage-0.

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

      (3)配置其他Babel插件同理,如我们要配置懒加载插件
      运行babel-plugin-syntax-dynamic-import
      在 .babelrc 文件中加入plugins配置:

       {
           "presets": ["env", "stage-0"],
      	 "plugins": ["transform-runtime","syntax-dynamic-import"]
       }
      

10.在webpack中导入其他包的方式

  • 使用npm下载包后,用import引入包名
    (1)运行npm i vue -D下载包;
    (2)在入口文件main.js中导入包import $ from 'vue',“from”后面跟着包名,这样就能使用vue包。

  • 如何改变import导入包的路径

    1. 方法一:在node_modules找对应包中的package.json,通过改变该文件中的module属性来改变引入的包文件
      需要改变包路径的原因: 默认的包可能是阉割版的,功能不齐全的,如vue,我们尝试的使用“render”,如下
      index.html

        <--index.html-->
      <body>
          <div id="app">
           </div>
      </body>
      
      	// main.js
      	import Vue from 'vue'
      	
      	var login = {
      	    template: '<h1>这是login组件</h1>'
      	  }
      	  
      	var vm = new Vue({
      	    el: '#app',
      	    data: {
      	      msg: '123'
      	    },
      	     components: {
      	       login
      	     },
      	     render: function (createElements) {
      	         return createElements(login)
      	         } 
      	  })
      

      然后通过webpack运行,结果是报以下错误
      在这里插入图片描述
      这是因为vue默认使用的是vue.runtime.common.js,这是功能不全的版本,这里我们首选我们要回顾一下包的查找规则:

      (1)找 项目根目录中有没有 node_modules 的文件夹
      (2)在 node_modules 中 根据包名,找对应的 vue 文件夹
      (3) 在 vue 文件夹中,找 一个叫做 package.json 的包配置文件
      (4)在 package.json 文件中,查找 一个 main 属性【main属性指定了这个包在被加载时候的入口文件】

      因此我们可以找到vue文件中package.json文件,发现他的main指定的路径是"module": "dist/vue.runtime.common.js",只要将该路径修改为"module": "dist/vue.js",即可使用完整版的VUE,完整版的文件大小是最大的。

    2. 方法二:通过webpack.config.js配置文件配置导入包的路径

      resolve: {
          alias: {     // 修改 Vue 被导入时候的包的路径
             "vue$": "vue/dist/vue.js"    //表示使用require或import时,如果是以vue结尾的,那么去vue/dist/vue.js下面找包
          }
        }
      

      注:这个引入方式的优先级大于第一种引入方式。

  • 使用npm下载包后,用import直接引入包路径
    (1)运行npm i vue -D下载包;
    (2)在入口文件main.js中导入包import Vue from '../node_modules/vue/dist/vue.js',“from”后面跟着包路径,这就是引入的包。

11.vue-loader——解析后缀为.vue文件(vue的组件)的插件

  • 步骤
    1. 运行cnpm i vue-loader vue-template-compiler -D,vue-template-compilervue-loader的内部依赖,也要安装。

    2. webpack.config.js文件中配置插件节点和匹配规则

      const VueLoaderPlugin = require('vue-loader/lib/plugin')     //第一步:引入插件
      module.exports = {
      	  plugins: [        // 第二步:配置插件的节点
      	    new VueLoaderPlugin()
      	  ],
      	  module: { // 第三步:配置以.vue结尾的匹配规则
      	    rules: [ 
      	      { test:/\.vue$/, use: 'vue-loader' }
      	    ]
      	  }
      	};  
      
    3. 在js入口文件main,js中引入以“.vue”结尾的vue文件

      index.html

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Document</title>
          <!-- <script src="/bundle.js"></script> -->
      </head>
      <body>
          <div id="app">
              <login></login>
           </div>
      </body>
      

      main.js
      注意:如果引入的vue包为默认配置的包,即vue.runtime.common.js时,则不支持以componets的形式引入组件,而应该使用render函数。

      import Vue from 'vue'
      import login from './login.vue'
      
      var vm = new Vue({
          el: '#app',
          data: {
            msg: '123'
          },
        //  components: {
        //     login
        //     },
           render: function (createElements) { 
               return createElements(login)
               } 
           //    render:  c => c(login)        //以上方式的简写
        })
      

      login.vue

      <template>
        <div>
          <h1>这是登录组件,使用 .vue 文件定义出来的 --- {{msg}}</h1>
        </div>
      </template>
      
      <script>
      export default {
        data() {
          // 注意:组件中的 data 必须是 function
          return {
            msg: "123"
          };
        },
        methods: {
          show() {
            console.log("调用了 login.vue 中的 show 方法");
          }
        }
      };
      </script>
      
      <style>
      
      </style>
      

12.vue-ressource

  • 作用:实现异步加载 Ajax
  • 用法:vue的ajax用法
  • 导入步骤
    1. 运行cnpm i vue-resource -D安装包;
    2. 在入口文件中导入
      import VueResource from 'vue-resource'
      Vue.use(VueResource)
      
  • 全局设置请求接口的根路径
import VueResource from 'vue-resource'
Vue.use(VueResource)
Vue.http.options.root = 'http://ledong.hmywater.com';//设置请求的根路径

用npm装插件

  1. 在终端上输出指令生成的默认的package.json:npm init -y
  2. 在终端上输出指令用npm i来直接安装模块:如安装jquery、bootstrap命令为,npm i jquery -Snpm i bootstrap -S安装的包放在node_modules
    扩展:
    -D后,安装包会在package中的 devDependencies对象中。简称dev。dev是在开发环境中要用到的。
    -S后,安装包会在package中的 dependencies 对象中。简称dep。dep是在生产环境中要用到的。
    举个例子:
    构建工具:gulp和webpack是用来压缩代码,打包等需要的工具,程序实际运行的时候并不需要,就要放在dev中所以要用 -D
    项目插件:例如element ui、echarts这种插件要在运行中使用的,就要放在dep中所以就用 -S
    一般我们项目插件,在api中都可以看到,一般都是-S。因为这些插件是在程序运行中使用的。
  3. 在项目的js入口文件(main.js)中导入模块的方法:import *** from *** 是ES6中导入模块的方式
    导入jquery模块:import $ from ‘jquery’,表示从node_modules导入jquery包,用$变量名来接收
  4. 直接在页面上引用main.js会报错,因为浏览器不认识import这种高级的JS语法,需要使用webpack进行处理,webpack默认会把这种高级的语法转换为低级的浏览器能识别的语法;
    在终端输出指令(打包指令):运行webpack 入口文件路径 输出文件路径
    如:webpack src/js/main.js dist/bundle.js
    把入口文件处理后存储在输入文件路径中

webpack 中如何使用 vue :

  1. 安装vue的包: cnpm i vue -S
  2. 由于 在 webpack 中,推荐使用 .vue 这个组件模板文件定义组件,所以,需要安装 能解析这种文件的 loader cnpm i vue-loader vue-template-complier -D
  3. 在 main.js 中,导入 vue 模块 import Vue from ‘vue’
  4. 定义一个 .vue 结尾的组件,其中,组件有三部分组成: template script style
  5. 使用 import login from ‘./login.vue’ 导入这个组件
  6. 创建 vm 的实例 var vm = new Vue({ el: ‘#app’, render: c => c(login) })
  7. 在页面中创建一个 id 为 app 的 div 元素,作为我们 vm 实例要控制的区域;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值