写点什么

Vue_Webpack 详解

作者:Studying_swz
  • 2022-10-25
    天津
  • 本文字数:7389 字

    阅读完需:约 24 分钟

Vue_Webpack详解

1.认识 webpack

  • webpack 是一个现代的 JavaScript 应用的静态模块打包工具

  • 1.模块化

  • 在 ES6 之前,我们要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发。

  • 并且在通过模块化开发完成了项目后,还需要处理模块间的各种依赖,并且将其进行整合打包。 而 webpack 其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系。

  • 而且不仅仅是JavaScript 文件,我们的CSS、图片、json文件等等在 webpack 中都可以被当做

  • 2.打包

  • 将 webpack 中的各种资源模块进行打包合并成一个或多个包(Bundle)

  • 并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。

  • 3.和 grunt/gulp 的对比

  • 如果你的工程模块依赖非常简单,甚至是没有用到模块化的概念。

  • 只需要进行简单的合并、压缩,就使用 grunt/gulp 即可。

  • 但是如果整个项目使用了模块化管理,而且相互依赖非常强,我们就可以使用更加强大的 webpack

2.webpack 的安装

  • 安装 node.js(https://nodejs.org/zh-cn/

  • 查看 node 版本 node -v

  • 全局安装 webpack npm install webpack@3.6.0 -g,指定了版本为 3.6.0

  • 局部安装 webpack cd 对应目录;npm install webpack@3.6.0 --save-dev

  • 其中--save-dev是开发时依赖,项目打包后不需要继续使用

  • 为什么全局安装后,还需要局部安装呢?

  • 在终端直接执行 webpack 命令,使用的全局安装的 webpack

  • 当在 package.json 中定义了 scripts 时,其中包含了 webpack 命令,那么使用的是局部 webpack

3.webpack 的起步

  • 创建目录结构


  • 文件和文件夹解析:

  • dist 文件夹:用于存放之后打包的文件

  • src 文件夹:用于存放我们写的源文件

  • main.js:项目的入口文件。

  • mathUtils.js:定义了一些数学工具函数,可以在其他地方引用,并且使用。

  • info.js:定义了一些变量信息

  • index.html:浏览器打开展示的首页 html

  • package.json:通过 npm init 生成的,npm 包管理的文件

  • mathUtils.js


  function add(num1,num2){      return num1 + num2;  }    function mul(num1,num2){      return num1*num2;  }    module.exports = {      add,      mul  }
复制代码


  • info.js


  export const name = 'why';  export const height = 180;
复制代码


  • main.js


  const {add,mul} = require('./mathUtils.js');    console.log(add(20,30));  console.log(mul(20,30));    import {name,height} from './info.js';  console.log(name);  console.log(height);
复制代码


注:可以看到main.js引入了其它js文件
复制代码


  • webpack 打包


  webpack ./src/main.js ./dist/bundle.js
复制代码


  • 打包后会在 dist 文件下,生成一个 bundle.js 文件

  • bundle.js 文件,是 webpack 处理了项目直接文件依赖后生成的一个 js 文件,我们只需要将这个 js 文件在 index.html 中引入即可

  • 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>  </head>  <body>     <script src="dist/bundle.js"></script>  </body>  </html>
复制代码

4.webpack 的配置

  • 目标:简化上面的打包命令

  • 1.创建 webpack.config.js 文件


  const path = require('path')    module.exports = {      entry : "./src/main.js",      output: {          path: path.resolve(__dirname,'dist'), //动态获取绝对路径,__dirname是node中全局变量          filename :  "bundle.js"      },  }
复制代码


  • 2.npm init,生成package.json文件,这里面是针对当前项目的主要描述文件(里面会生成所有安装的依赖)


  • 3.局部安装 webpack---- cd 当前目录;npm install webpack@3.6.0 --save-dev,生成 node 模块


  • 4.配置 package.json 文件,简化命令


  • 5.命令npm run build

5.loader 的使用

  • 在开发中我们不仅仅有基本的 js 代码处理,我们也需要加载 css、图片,也包括一些高级的将 ES6 转成 ES5 代码,将 TypeScript 转成 ES5 代码,将 scss、less 转成 css,将.jsx、.vue 文件转成 js 文件等等

  • 对于 webpack 本身的能力来说,对于这些转化是不支持的。需要 webpack 扩展对应的 loader

  • loader 使用过程:

  • 步骤一:通过 npm 安装需要使用的 loader

  • 步骤二:在 webpack.config.js 中的 modules 关键字下进行配置

5.1 css 的 loader 使用

  • 1.创建 css 文件


  body {      background-color:red;   }
复制代码


  • 2.main.js 引用


  //1.使用commonjs的模块化规范  const {add,mul} = require('./js/mathUtils.js');    console.log(add(20,30));  console.log(mul(20,30));    //2.使用ES6的模块化规范  import {name,height} from './js/info.js';  console.log(name);  console.log(height);      //3.依赖css文件  require("./css/normal.css")
复制代码


  • 3.run build 打包(报错)

  • 4.https://v4.webpack.docschina.org/loaders/,配置 cssloader 文档

  • 5.npm install --save-dev css-loader@2.0.2

  • 6.npm install style-loader@0.23.1 --save-dev

  • 7.配置 webpack.json.js 文件

  • 8.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>  </head>  <body>      你好   <h2>       你好   </h2>  <script src="dist/bundle.js"></script>  </body>  </html>
复制代码

5.2 less 的 loader 使用(同理)

  • 1.创建 less 文件


  @fontSize: 50px;  @fontColor: orange;    body{      font-size: @fontSize;      color: @fontColor;  }
复制代码


  • 2.引入 less 文件(main.js)


  //1.使用commonjs的模块化规范  const {add,mul} = require('./js/mathUtils.js');    console.log(add(20,30));  console.log(mul(20,30));    //2.使用ES6的模块化规范  import {name,height} from './js/info.js';  console.log(name);  console.log(height);      //3.依赖css文件  require("./css/normal.css")    //4.依赖less文件  require("./css/special.less")
复制代码


  • 3.npm install less-loader@4.1.0 --save-devnpm install less@3.9.0 --save-dev

  • 4.配置 webpack.json.js 文件

  • 5.打包 run build

5.3 图片文件处理

  • 1.创建 img 文件

  • 2.修改 css 文件


  body {      /* background-color:red; */      background-image: url("../img/timg.jpg");  }
复制代码


  • 3.直接打包会出错,需要安装 url-loader 包 npm install url-loader@1.1.2 --save-dev

  • 4.修改 webpack.json.js 文件

  • 5.这时候打包会成功,但是换了一张的图片就会报错

  • 6、安装 file-loader 处理大文件npm install file-loader@3.0.1 --save-dev

  • 7、再次打包即可成功

  • 注:可以发现,对于大的图片打包成功会输出到 dist 文件夹下,此时引用的话会找不到,需要配置下路径

  • 8.修改 webpack.config.js

  • 9.另外对于生成的图片名字太长,我们可以配置下生成规则--webpack.config.js,表示生成名字+8位哈希值+扩展名

5.4 babel 的使用(es6 转 es5)

  • 1.npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

  • 2.配置 webpack.json.js 文件

  • run build

6.webpack 中配置 Vue

6.1 引入 vue.js

  • 1 . npm install vue@2.5.21 --save 因为我们后续是在实际项目中也会使用 vue 的,所以并不是开发时依赖

  • 2 . main.js 引入


  //1.使用commonjs的模块化规范  const {add,mul} = require('./js/mathUtils.js');    console.log(add(20,30));  console.log(mul(20,30));    //2.使用ES6的模块化规范  import {name,height} from './js/info.js';  console.log(name);  console.log(height);      //3.依赖css文件  require("./css/normal.css")    //4.依赖less文件  require("./css/special.less")    //5.使用Vue进行开发  import Vue from "vue"  new Vue({      el:'#app',      data:{          name : 'codewhy'      }  })
复制代码


  • 3.run build(报错)---这个错误说的是我们使用的是 runtime-only 版本的 Vue,


  • 4.修改 webpack.config.js 配置,即可成功


  • 5.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>  </head>  <body >      <div id="app">          你好      </div>     <h2>       你好   </h2>  <script src="dist/bundle.js"></script>  </body>  </html>
复制代码

6.2 el 和 template 的区别

  • 正常运行之后,我们来考虑另外一个问题:

  • 如果我们希望将 data 中的数据显示在界面中,就必须是修改 index.html

  • 如果我们后面自定义了组件,也必须修改 index.html 来使用组件

  • 但是 html 模板在之后的开发中,我并不希望手动的来频繁修改,是否可以做到呢?

  • 定义 template 属性:

  • 在前面的 Vue 实例中,我们定义了 el 属性,用于和 index.html 中的 #app 进行绑定,让 Vue 实例之后可以管理它其中的内容

  • 这里,我们可以将 div 元素中的{{message}}内容删掉,只保留一个基本的 id 为 div 的元素

  • 但是如果我依然希望在其中显示{{message}}的内容,应该怎么处理呢?

  • 我们可以再定义一个 template 属性,代码如下:

  • 那么,el 和 template 模板的关系是什么呢?

  • 在我们之前的学习中,我们知道 el 用于指定 Vue 要管理的 DOM,可以帮助解析其中的指令、事件监听等等。

  • 而如果 Vue 实例中同时指定了 template,那么 template 模板的内容会替换掉挂载的对应 el 的模板。

  • 这样做有什么好处呢?

  • 这样做之后我们就不需要在以后的开发中再次操作 index.html,只需要在 template 中写入对应的标签即可

6.3 分离 template 模板

  • 书写 template 模块非常麻烦怎么办呢?

  • 没有关系,稍后我们会将 template 模板中的内容进行抽离。

  • 会分成三部分书写:template、script、style,结构变得非常清晰。

  • 1 .App.vue 文件


   <template>      <div>          <h2 class="title">{{message}}</h2>          <button @click="btnClick">按钮</button>          <h2>{{name}}</h2>          <Cpn/>      </div>  </template>      <script>  import Cpn from "./Cpn.vue"  export default {      name:"App",      components: {        Cpn        },       data(){          return {              name : 'codewhy',              message:"123"          }      },      methods:{          btnClick(){            }      }  }  </script>    <style scoped>      .title{          color:green;      }  </style>
复制代码


  • 2 .子组件 Cpn.vue 文件


   <template>      <div>          <h2 class="title">我是cpn组件的标题</h2>          <p>我是cpn组件的内容</p>          <h2>{{name}}</h2>      </div>  </template>      <script>  export default {      name:"Cpn",       data(){          return {              name : 'Cpn的组件的name',          }      },      methods:{          btnClick(){            }      }  }  </script>    <style scoped>      .title{          color:green;      }  </style>
复制代码


  • 3 .main.js 引入 App.vue


  //1.使用commonjs的模块化规范  const {add,mul} = require('./js/mathUtils.js');    console.log(add(20,30));  console.log(mul(20,30));    //2.使用ES6的模块化规范  import {name,height} from './js/info.js';  console.log(name);  console.log(height);      //3.依赖css文件  require("./css/normal.css")    //4.依赖less文件  require("./css/special.less")    //5.使用Vue进行开发  import Vue from "vue"  // import App from "./vue/app"  import App from './vue/App.vue'    const  app = new Vue({      el:'#app',      // 如果同时有el和template,会直接用template 替换掉el内容      template:`          <App/>      `,      components:{          App      }  })
复制代码


  • 4 .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>  </head>  <body >      <div id="app">          你好      </div>     <h2>       你好   </h2>  <script src="dist/bundle.js"></script>  </body>  </html>
复制代码

7.认识 plugin

7.1 添加版权声明

  • 在 webpack.config.js 配置如下

  • 重新打包

7.2 HtmlWebpackPlugin

  • 目的:将 index.html 打包到 dist 中

  • 1.安装插件npm install html-webpack-plugin@3.2.0 --sava-dev

  • 2.在webpack.config.js导入


  • 3.因为 index.html 的 js 打包后会自动引入,所以注释了 dist 以及下面的内容


  <!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 id="app">          你好      </div>  <!-- <script src="dist/bundle.js"></script> -->  </body>  </html>
复制代码


  • 4.最后生成的如下

7.3 压缩 js 的插件

  • 1.npm install uglifyjs-webpack-plugin@1.1.1 --save-dev

  • 2.配置 webpack.config.js

  • 3.npm run build

  • 对 js 丑化

8.plugin 的使用搭建本地服务器🚲

  • webpack 提供了一个可选的本地开发服务器,这个本地服务器基于 node.js 搭建,内部使用 express 框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果。

  • 不过它是一个单独的模块,在 webpack 中使用之前需要先安装它

  • npm install --save-dev webpack-dev-server@2.9.1

  • 修改 webpack.config.js

  • devserver 也是作为 webpack 中的一个选项,选项本身可以设置如下属性:

  • contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist

  • port:端口号

  • inline:页面实时刷新

  • historyApiFallback:在 SPA 页面中,依赖 HTML5 的 history 模式


  • 修改 package.json 文件


  • 开始热部署npm run dev

    这样就会实现,当文件改变的时候,页面会自动修改,因为此时这些修改保存到了内存中,类似于 java 的热部署

  • 补充 1:(自动打开链接)


  • 补充 2:js 压缩在开发中,不应该使用


9.webpack 的配置分离🚊

  • 目的:开发时,使用一个配置文件;发布时使用另一个配置文件

  • npm install webpack-merge@4.1.5 --save-dev 安装 merge 包,用于合并下面的配置文件

  • 所以将 webpack.config.js 抽离成 3 个文件

  • 1 . base.config.js


  const path = require('path')  const webpack  = require('webpack')  const HtmlWebpackPlugin = require('html-webpack-plugin')  const uglifyjsWebpackPlugin = require('uglifyjs-Webpack-plugin')  module.exports = {      entry : "./src/main.js",      output: {          path: path.resolve(__dirname,'../dist'), //动态获取绝对路径,__dirname是node中全局变量          filename :  "bundle.js",          //publicPath: 'dist/'      },      plugins:[        new webpack.BannerPlugin('最终版权swz所有!'),        new HtmlWebpackPlugin({          template:'index.html'        }),        //new uglifyjsWebpackPlugin()      ],      module: {          rules: [              {                   test: /\.css$/,                  // style-loader 将模块的导出作为样式添加到 DOM 中                  // css-loader 解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码                  //使用多个loader时,是从右向左                  use: ['style-loader','css-loader']               },              {                  test: /\.less$/,                  use: [{                      loader: 'style-loader' // creates style nodes from JS strings                    }, {                      loader: 'css-loader' // translates CSS into CommonJS                    }, {                      loader: 'less-loader' // compiles Less to CSS                  }]              },              {                  test: /\.(png|jpg|jpeg|gif)$/i,                  use: [                    {                      loader: 'url-loader',                      options: {                          //当加载的图片,小于limit时,会将图片编译成base64字符串形式                          //反之,需要使用file-loader没模块进行加载                        limit: 13000,                        //[]表示变量                       name: 'img/[name].[hash:8].[ext]'                      }                    }                  ]              },              {                  test: /\.m?js$/,                  //exclude 排除,include包含                  exclude: /(node_modules|bower_components)/,                  use: {                    loader: 'babel-loader',                    options: {                      presets: ['es2015']                    }                  }                },                {                  test: /\.vue$/,                  use: ['vue-loader']                }          ]      },      resolve:{        alias: {          'vue$':"vue/dist/vue.esm.js"        }      }  }
复制代码


  • 2 . prod.config.js


  const uglifyjsWebpackPlugin = require('uglifyjs-Webpack-plugin')  const webpackMerge = require('webpack-merge')  const baseConfig = require('./base.config')    module.exports = webpackMerge(baseConfig, {        plugins:[        new uglifyjsWebpackPlugin()      ]  })
复制代码


  • 3 . dev.config.js


  const webpackMerge = require('webpack-merge')  const baseConfig = require('./base.config')  module.exports = webpackMerge(baseConfig, {      devServer:{        contentBase: "./dist",        inline: true      }  })
复制代码


  • 修改配置文件 package.json

  • 注:以上安装的模块的版本要对应!!!

发布于: 刚刚阅读数: 4
用户头像

Studying_swz

关注

还未添加个人签名 2020-12-23 加入

还未添加个人简介

评论

发布
暂无评论
Vue_Webpack详解_Vue_Studying_swz_InfoQ写作社区