019 Vue webpack的使用

[A] webpack的简介

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

            1. 在开发中,我们可能生成多种格式的文件,如.js, .hbs, .png, sass等等,而最终我们只需要.js, .png, .css文件

                webpack可以帮助我们实现文件的自动打包和格式转换

            2. 在开发中,模块化开发有很多规范,如CommonJS,AMD, CMD, ES6规范等,但是浏览器只支持ES6规范,缺乏支持其他规范的底层支撑

                webpack可以提供这种底层支撑,使得开发时可以随意使用各种规范

            3. 在开发中,模块化的开发会使得哥哥模块之间存在错综复杂的依赖,先后顺序处理不好会运行报错

                webpack可以帮助我们自动化的处理各种依赖关系

            4. 在webpack中,不仅.js被看作模块,图片,CSS,json文件等等都被看作是模块对待

  

  2. webpack的两个核心是:模块和打包

                    模块:

                        1. 在ES6之前,我们要进行模块化开发,就要借助其他工具实现模块化,

                            并且在模块化开发完项目后,还要处理模块之间的依赖关系,将其整合打包

                        2. webpack的一个核心就是进行模块化,并且处理好模块之间的依赖关系

                        3. 在webpack中,js文件,css文件,图片,json文件都可以被视作模块来使用

                    打包:

                        1. 打包就是,webpack将隔俄国模块进行整理打包成一个或者多个包

                        2. 在打包的过程中可以对资源进行处理,

                            比如压缩图片,将scss转化成css,ES6语法转化成ES5语法,Typescript转化成JavaScript等等

        3. webpack与gulp/grunt的对比

            1. gulp/grunt的核心是task

                首先,我们配置一系列的task,并且定义task要处理的事物(图片压缩,ES6版本转换,scss转成css)

                然后,让gulp/grunt来自动化的执行这些task,而且整个流程自动化执行

                因此,gulp/grunt被称为前端自动化任务管理工具

            2. 什么时候用gulp/grunt

                首先,工程模块依赖关系非常简单,甚至没有模块化的概念

                其次,只需要进行简单的合并,压缩,使用gulp/grunt即可

                但是,如果整个项目依赖关系复杂,使用模块化管理,就得考虑webpack了

            3. 区别

                gulp/grunt更加强调前端流程的自动化,模块不是它的核心

                webpack更加强调模块化开发管理,而文件合并,图片压缩只是它的附带功能

  4. webpack的运行依赖于node环境.

                    node环境为了能够执行更多的代码,其中包含了一个包管理器cpm(node package manager)

[B] webpack的安装

  安装webpack(在某个nodejs版本里)

                1. webpack全局安装

                      控制台指令:

                             npm install webpack -g

                              也可以指定webpack版本:

                             npm install webpack@3.6.0 -g

                2. webpack本地安装:

                      控制台指令:

                               npm install webpack --save-dev

                                也可以指定webpack版本:

                               npm install webpack@3.6.0 --save-dev

          为什么全局安装之后还要本地安装呢

                        因为在控制台(CMD控制台,console等平台)上运行的webpack命令时调用的是全局webpack

                        但在html,js文档中调用不到全局webpack指令,需本地下载

[C] webpack 的配置文件

    webpack的配置文件有两个:webpack.config.js和package.json的配置,配置好这两个文件后,我们在控制台直接运行webpack,即可将指定的文件打包并放在指定的位置

  1. 配置webpack.config.js文件

                    1. 指定默认的入口文件名,默认为main.js

                    2. 指定默认的出口文件名, 默认为bundle.js

                    添加package.json文件:

                            1. 在当前目录下,新建一个文件,名为webpack.config.js、

                            2. 在该文件中添加内容如下:

const path = require("path");
module.exports = {
    entry: "./src/main.js",
    output: {
        path: path.resolve(__dirname, 'dist'),
        // path是一个模块,resolve方法是将导入的两个路径进行连接
        // __dirname指的是当前文件所在的路径
        filename: "bundle.js"
    }
}

               

  2.  配置package.json文件

                        记录node中开发的配置信息

                    1. 在该文件中,可以将webpack指令和npm run 指令对应起来

                            如在package.json文件中的script对象中添加:

                                build: "webpack",

                            则此后,在控制台输入npm run build,等价于输入webpack

                    2. 在终端和CMD控制台运行的webpack命令都是调用全局的webpack包,

                        而package.json中的script中的指令首先查找本地的webpack包,若没有找到再去全局查找

[D] webpack中的loader

    loader时webpack中的一个非常核心的概念,loader是一个哦你沟通的概念,并非指某一个文件或者插件

      1. loader能做什么

               1. webpack可以处理js文件,并且处理js文件之间的依赖关系。

               2. 到那时开发中,除了处理js文件,还要处理css, 图片,sass和less转为css,

                     ES6转为ES5, TypeScript转化为ES5 .jsx, .vue转化为js文件等等内容

               3. webpackk本身解决不了这么多问题,但是webpack拓展的loader可以处理这些问题

       2. loader的使用

                1. 通过npm本地安装loader

                        安装地址:https://www.webpackjs.com/concepts/

                        安装指令:npm install --save-dev loader名

                2. 在入口文件中导入所需要打包的文件(.css, png,等等一系列文件),使得入口文件依赖于这些文件,方便打包

                        即在main.js文件中添加命令:

                                require("文件");

               3. 在webpack.config.js中的modules关键字下进行配置

                            将下载的loader告诉webpack.config.js文件,即在该文件中新增一个module对象。

                                module对象:

module: {
    rules: [
        {
            test: /.css$/,
             use: ["loader名"]
        }
    ]
}

              loader的使用示例1: 配置并使用.css打包工具

                        1. 编写一个.css文件,命名为cssStyle.css

                        2. 在webpack的入口文件中导入该css模块,使得入口文件依赖于cssStyle.css文件

                                具体操作:

                                    在入口文件中加入指令:

                                        require("../css/cssStyle.css");

                        3. 本地下载和安装css打包的工具

                                下载地址:https://www.webpackjs.com/concepts/

                                具体操作:

                                    npm install --save-dev css-loader

                                    npm install style-loader --save-dev

                        4. 配置webpack.config.js文件

                            在webpack.config.js文件的module.exports对象中新增一个module对象

                                module对象:

module: {
    rules: [
        {
            test: /.css$/,
            use: [
                { loader: "style-loader" },
                { loader: "css-loader" }
            ]
        }
    ]
}

                            【注】style-loader:将模块的导出作为样式添加到 DOM 中

                                  css-loader:   解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码

                                在use中的读取顺序是从右向左,这两个文件的顺序不能错

             loader的使用示例2: 配置并使用.less打包工具

                        1. 编写一个.less文件,命名为lessStyle.less

                        2. 在webpack的入口文件中导入该less模块,使得入口文件依赖于lessStyle.less文件

                                具体操作:

                                    在入口文件中加入指令:

                                        require("../css/lessStyle.less");

                        3. 本地下载和安装css打包的工具

                                下载地址:https://www.webpackjs.com/concepts/

                                具体操作:

                                    npm install --save-dev less-loader

                                    npm install --save-dev style-loader

                                    npm install less --save-dev

                        4. 配置webpack.config.js文件

                            在webpack.config.js文件的module.exports对象中的module对象中的rules数组中新增一个数组元素

{
    test: /.less$/,
    use: ["style-loader", "css-loader", "less-loader"]
}

             loader的使用示例3: 配置并使用图片打包工具

                            当css,js文件中有图片时,需要下载打包图片的loader

                        1. 本地下载和安装css打包的工具

                                下载地址:https://www.webpackjs.com/concepts/

                                具体操作:

                                    npm install --save-dev url-loader

                        2. 配置webpack.config.js文件

                            在webpack.config.js文件的module.exports对象中的module对象中的rules数组中新增一个数组元素

{
    test: /.(png|jpg|gif)$/,
    use: [
        {
            loader: 'url-loader',
            options: {
                // 图片大小限制,单位为B
                // 当图片实际大小在limit范围内时,只下载url-loader即可,图片会被转化为base64格式的文件
                // 当图片大小超过limit范围是,还要瞎子啊file-loader,此时图片会以哈希值命名并保存到目标文件夹中
                // 此时,文件调用会因为路径变了而报错,因此须在本配置文件的output对象中添加元素:publicPath: "dist/"
                limit: 1500,
                // 这里的name值是对打包的图片的路径和名字做限制的
                name: "img/[name].[hash:8].[ext]"
            }
        }
    ]
}

              loader的使用示例4: ES6转化成ES5的babel

                            ES6中的一些语法在ES5中不支持,为了更大限度的兼容,有时候需将ES6转化成ES5

                        1. 本地下载和安装css打包的工具

                                下载地址:https://www.webpackjs.com/concepts/

                                具体操作:

                                    npm install babel-loader babel-core babel-preset-es2015

                                【注】版本要对的上使用时才不会报错

                                检查:

                                    "babel-loader": "^7.1.5",

                                    "babel-core": "^6.26.3",

                                    "babel-preset-es2015": "^6.24.1",

                        2. 配置webpack.config.js文件

                            在webpack.config.js文件的module.exports对象中的module对象中的rules数组中新增一个数组元素

{
    test: /.js$/,
    // exclude排除,即在node_modules|bower_components这两个文件夹中的js不参与打包
     exclude: /(node_modules|bower_components)/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: ['es2015']
        }
    }
}

[E] plugin的使用

  1. plugin使插件的意思,通常指用于对现有的架构进行拓展

  2. webpack中的插件,及时对webpack中现有功能的拓展,比如打包优化,文件压缩等等

  3. loader与plugin的区别

    1. loader主要用于转换某些文件的模块,他是一个转换器

    2. plugin是插件,是对webpack本身的扩展,是一个扩展器

  4. plugin的使用

    1. 通过npm安装需要的plugins(某些wbpack内置的插件不需要安装)

    2. 在webpack.config.js中的plugins中配置插件

  

  plugin使用案例:

                    1. 添加版权说明 BannerPlugin插件

                          1. BannerPlugin插件是webpack自带的一个插件,在webpack.config.js中直接导入webpack包即可

                              const webpack = require("webpack");

                          2. 在webpack.config.js文件中的module.exports内添加plugins元素:

                              plugins:[

                                  new webpack.BannerPlugin("最终版权归Carrey所有")

                              ]

                   

                    2. 打包html文件的插件:HtmlWebpackPlugin插件

                          1. 安装HtmlWebpackPlugin插件

                              npm install html-webpack-plugin --save-dev

                          2. 在webpack.config.js文件中的plugins中添加配置信息

                              const HtmlWebpackPlugin = require("html-webpack-plugin");

                              new HtmlWebpackPlugin({

                                  template:'index.html'

                                  // 以这个文件为模板生成html文件

                              })

                       

                    3. 压缩js文件的插件:uglifyjs插件

                          1. 安装uglifyjs插件

                              npm install uglifyjs-webpack-plugin --save-dev

                          2. 在webpack.config.js文件中的plugins中添加配置信息

                              const uglifyjsPlugin = require("uglifyjs-webpack-plugin");

                              new uglifyjsPlugin()

[F] webpack中配置vue

       如果在项目中需要使用vue,则需要先安装,由于开发完之后依然依赖vue,因此vue是运行时依赖

  1. 安装vue:npm run vue --save

  2. 安装vue的三种方式:

                    1. 直接下载vue.js引用

                    2. CND引入

                    3. npm安装vue模块

  3. 引入vue实例

                    1. 在main.js中引入vue模块,并创建vue实例

import Vue from 'vue'
const app = new Vue({
    el: "#app",
    data: {
        msg: 'hello Carrey'
    }
})    

                    2. 将创建的这个app实例添加到index.html文件中

<body>
    <div id="app">
        <h2>{{msg}}</h2>
    </div>
</body>

  
  4. 在上述3中会出现引用失败或无效的情况

                    原因:

                            vue在发布的时候有两个版本,分别是runtime-only和runtime-compiler

                        1. runtime-only 该版本不允许代码中有任何的template,因为无法编译

                        2. runtime-compiler 该版本允许代码中有template,因为有专门的模块进行解析

                        3. 而我们在main.js中通过 el: "#app" 方式引入的就是在index.html中定义的template模板

                    解决:

                        1. 在webpack.config.js中进行相关配置,如下:

                            输出元素中添加resolve元素

module.exports = {
    resolve: {
        // alias: 别名
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    }
}

                    解决原理:

                        1. 引用vue模块式默认引用的是vue发布的runtime-only版本,但是该版本不能编译template模板

                        2. 通过webpack.config.js中的配置(如上配置),就可以指定引用的vue文件为vue.esm.js,

                            这是一个runtime-compiler版本,就可以编译template模板了

  5. vue实例中,el与template的区别

                        在上述3引入vue实例时,我们是将模板内容写在index.html中

                        即:

<body>
    <div id="app">
        <h2>{{msg}}</h2>
    </div>
</body>    

                        而实际开发中,我们不把模板内容写在index.html文件中,而是写在main.js中创建的实例中

                        即:

import Vue from 'vue'
const app = new Vue({
    el: "#app",
    template: `
        <div id="app">
            <h2>{{msg}}</h2>
        </div>
    `
    data: {
         msg: 'hello Carrey'
    }
}

                        此时index.html文件中只保留引入实例的div

                        即:

<body>
        <div id="app">
    </div>
</body>

                    那么el和template到底什么关系呢 ?

                            实际上我们在实际开发中,不希望频繁修改index.html中的内容,

                            但是我们又需要频繁修改index.html中显示的内容(即index.html中的模板内容),怎么办呢

                        使用el时,我们在vue实例中通过el属性与index.html中的#app绑定,之后vue实例就可以管理其中的内容了

                        而当同时定义了el属性和template属性时,template中定义的模板会替换掉el绑定的那个组件的内容

  6. 组件模板的抽离及vue的终极使用方案

                    在上述5中的使用方案中,我们可以进一步将组件抽离,以简化Vue实例

                        1. 在Vue实例中,我们可以将模板,数据以及方法全都抽出来

                        2. 将抽离出来的内容组合成一个组件,写在.vue文件中

                        3. 在vue实例中将这个.vue文件当作一个子组件,在Vue实例中引入并注册。

                    解决.vue文件通过webpack打包报错的问题:

                        1. 这是因为.vue文件,webpack并不认识,无法加载

                        2. 通过配置对应的loader帮助加载

                            npm install vue-loader vue-template-compiler --save-dev

                        3. 在webpack.config.js中进行相关配置

module:{
    rules: [
        {
            test: /.vue$/,
            use: ['vue-loader']
        }
    ]
},

                        4. 若此时通过npm run build 打包文件报错,需要如下操作:

                                遇到报错注意查看报错信息

                            1. 在webpack.config.js中需要安装配套的plugin

// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
    // ...
    plugins: [
        new VueLoaderPlugin()
    ]
}

 [G] webpack搭建本地服务器 webpack-dev-server插件

     在开发过程中,一旦修改保存代码,我们就希望看到运行结果,但是每次都需要webpack打包,然后手动运行,这样过于繁琐

    因此我们可以搭建本地服务器,代码发生变动后,自动编译执行并展示在浏览器上

  1.  webpack-dev-server简介

    这是webpack提供的一个可选的本地开发服务器,这个本地服务器是给予nodejs搭建的,内部使用express框架,可以实现想要的让浏览器自动刷新显示我们修改后的结果

  2. 安装 webpack-dev-server

    终端运行:npm install  webpack-dev-server --save-dev

    这个服务器只在开发时便于观察所写代码的运行结果,运行时不需要,因此为开发时依赖。

       3. 在webpack.config.js文件中的module.exports中新增添加配置信息

                    devServer:{

                        contentBase: "./dist",

                        inline: true

                    }

 

  4. 使用本地webpack-dev-server插件启动这个服务器

    在package.json中配置script指令,使用本地包启动服务器

    "dev": "webpack-dev-server"

 

  5. 当使用npm run webpack-dev-server运行这个服务器时,就会启动一个服务器

    当我们需要这个服务器自动打开浏览器网页时,可以将第3步中的指令改为:"dev": "webpack-dev-server --open"

[H] 配置文件的抽离

    webpack.config.js中的配置文件显的有写冗杂,开发时我们需要将该配置文件进行分离 。 

    将基本的配置信息单独写在一个文件中,将仅在开发时依赖的配置信息单独写在一个配置文件中,将仅在运行时依赖的配置信息单独写在一个配置文件中。

  1. 我们将配置文件webpack.config.js拆分成三个文件:基本配置 base.config.js文件,开发时依赖配置 dev.config.js文件 和 运行时依赖配置 prod.config.js文件。

  2. 原webpack.config.js文件中,存在的属性:

    1. entry:入口文件路径

    2. output:目标文件路径

    3. module:loader配置信息

    4. resolve:解决模块请求时的问题

    5. plugins:配置插件

    6. devServer:搭建本地服务器

const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const uglifyjsPlugin = require("uglifyjs-webpack-plugin");

module.exports = {
    entry: "./src/js/main.js",
    output: {
        path: path.resolve(__dirname, 'dist'),
        // path是一个模块,resolve方法是将导入的两个路径进行连接
        // __dirname指的是当前文件所在的路径
        filename: "bundle.js",
        
        // 保存图片的地址
        // publicPath: "dist/"
    },
    module: {
        rules: [
            {
              test: /.css$/,
              use: ["style-loader","css-loader" ]
            },
            {
                test: /.less$/,
                use: ["style-loader", "css-loader", "less-loader"]
            },
            {
                test: /.(png|jpg|gif)$/,
                use: [
                  {
                    loader: 'url-loader',
                    options: {
                        // 图片大小限制,单位为B
                      limit: 1500,
                      name: "img/[name].[hash:8].[ext]"
                    }
                  }
                ]
            },
            {
              test: /.js$/,
              // exclude排除,即在node_modules|bower_components这两个文件夹中的js不参与打包
              exclude: /(node_modules|bower_components)/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: ['es2015']
                }
              }
            },
            {
              test: /.vue$/,
              use: ["vue-loader"]
            }
        ]
    },
    resolve:{
      // alias 别名
      alias:{
        "vue$": "vue/dist/vue.esm.js"
      }
    },
    plugins:[
      new webpack.BannerPlugin("最终版权归Carrey所有"),
      new HtmlWebpackPlugin({
        template:'index.html'
      }),
      new uglifyjsPlugin(),
    ],
    devServer: {
      contentBase: "./dist",
      inline: true
    }
}
View Code

  3. 基本配置文件 base.config.js文件

    1. entry:入口文件路径

    2. output:目标文件路径

    3. module:loader配置信息

    4. resolve:解决模块请求时的问题

const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const uglifyjsPlugin = require("uglifyjs-webpack-plugin");

module.exports = {
    entry: "./src/js/main.js",
    output: {
        path: path.resolve(__dirname, 'dist'),
        // path是一个模块,resolve方法是将导入的两个路径进行连接
        // __dirname指的是当前文件所在的路径
        filename: "bundle.js",
        
        // 保存图片的地址
        // publicPath: "dist/"
    },
    module: {
        rules: [
            {
              test: /.css$/,
              use: ["style-loader","css-loader" ]
            },
            {
                test: /.less$/,
                use: ["style-loader", "css-loader", "less-loader"]
            },
            {
                test: /.(png|jpg|gif)$/,
                use: [
                  {
                    loader: 'url-loader',
                    options: {
                        // 图片大小限制,单位为B
                      limit: 1500,
                      name: "img/[name].[hash:8].[ext]"
                    }
                  }
                ]
            },
            {
              test: /.js$/,
              // exclude排除,即在node_modules|bower_components这两个文件夹中的js不参与打包
              exclude: /(node_modules|bower_components)/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: ['es2015']
                }
              }
            },
            {
              test: /.vue$/,
              use: ["vue-loader"]
            }
        ]
    },
    resolve:{
      // alias 别名
      alias:{
        "vue$": "vue/dist/vue.esm.js"
      }
    },
}
View Code

  4. 开发时依赖的配置文件 dev.config.js 文件

    6. devServer:搭建本地服务器

// dev.config.js
module.exports = {
    devServer: {
      contentBase: "./dist",
      inline: true
    }
}
View Code

  5. 运行时依赖的配置文件 prod.config.js文件

    5. plugins:配置插件

// prod.config.js
const uglifyjsPlugin = require("uglifyjs-webpack-plugin");

module.exports = {
    plugins:[
      new webpack.BannerPlugin("最终版权归Carrey所有"),
      new HtmlWebpackPlugin({
        template:'index.html'
      }),
      new uglifyjsPlugin(),
    ],
}
View Code

  6. 文件的合并

      配置文的分离是为了便于开发,但分离的配置文件最终还是要合并的

    1. 安装webpack-merge包,用于合并文件

      终端运行:npm install webpack-merge --save-dev

      开发时依赖,运行时不需要

    2.dev.config.js文件的合并,在配置文件中调用webpack-merge包,对文件进行合并

// dev.config.js
// 导入webpack-merge包,用于合并文件
const webpackMerge = require('webpack-merge')
// 导入基本配置文件,并将其和本文件进行合并后导出
const baseConfig = require('./base.config.js')

module.exports = webpackMerge(baseConfig,{
    devServer: {
      contentBase: "./dist",
      inline: true
    }
})
View Code

    3. prod.config.js文件的合并,在配置文件中调用webpack-merge包,对文件进行合并

// prod.config.js
const uglifyjsPlugin = require("uglifyjs-webpack-plugin");
// 导入webpack-merge包
const webpackMerge = require('webpack-merge')
// 导入基本配置文件,并将其与本文件合并后到处
const baseConfig = require('./base.config.js')

module.exports = webpackMerge(baseConfig,{
  plugins:[
    new webpack.BannerPlugin("最终版权归Carrey所有"),
    new HtmlWebpackPlugin({
      template:'index.html'
    }),
    new uglifyjsPlugin(),
  ],
})
View Code

    4. 至此,配置文件的拆分和合并都完成了,可以删掉原来的配置文件webpack.config.js了

  7. 配置文件合并后,无法直接使用该配置文件,会出现两个问题

    问题1:提示没有找到配置文件webpack.config.js,这是因为vue默认的配置文件名为webpack.config.js,而现在只有base.config.js文件,dev.config.js文件 和  prod.config.js文件

        解决:

          在package.json文件中人为的指定配置文件

  "scripts": {
    // 这里的./build/prod.config.js和./build/prod.config.js分别为配置文件所在路径
    "build": "webpack --config ./build/prod.config.js",
    "dev": "webpack-dev-server --open --config ./build/prod.config.js",
  },

    问题2:打包后的文件没有保存在指定的dist文件中,而是在配置文件 prod.config.js 的路径下      

        这是因为在base.config.js中,output出口文件路径为 path: path.resolve(__dirname, 'dist'), 这里__dirname获取的是当前路径,即合并到prod.config.js 后的路径(即 prod.config.js 的路径)

       解决:

          在出口文件中的路径改为:path: path.resolve(__dirname, '../dist')  返回上一层的dist文件夹中,实际在哪根据需要修改

原文地址:https://www.cnblogs.com/carreyBlog/p/14060262.html