4.Webpack详解

webpack基础

认识webpack

webpack是一个现代的JavaScript应用的静态模块打包工具。
webpack.png
涉及到两个概念:模块打包css

模块

经过模块化开发完成项目后,还须要处理模块间的各类依赖,而且将其进行整合打包。而webpack其中一个核心就是让咱们可能进行模块化开发,而且会帮助咱们处理模块间的依赖关系。并且不只仅是JavaScript文件,咱们的CSS、图片、json文件等等在webpack中均可以被当作模块来使用。这就是webpack中模块化的概念。html

打包

就是将webpack中的各类资源模块进行打包合并成一个或多个包(Bundle)。而且在打包的过程当中,还能够对资源进行处理,好比压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操做。前端

但打包的操做彷佛grunt/gulp也能够帮助咱们完成,它们有什么不一样呢?vue

和grunt/gulp的对比

grunt/gulp的核心是Task
咱们能够配置一系列的task,而且定义task要处理的事务(例如ES六、ts转化,图片压缩,scss转成css)。以后让grunt/gulp来依次执行这些task,并且让整个流程自动化。因此grunt/gulp也被称为前端自动化任务管理工具。node

来看一个gulp的task:下面的task就是将src下面的全部js文件转成ES5的语法。而且最终输出到dist文件夹中。webpack

const gu1p = requireC('gulp');
const babe1 = require('gu1p-babe1');
gulp.task('js',()=>
    gulp.src('src/*.js')
        .pipe(babe1({
            presets: ['es2015']
        }))
        .pipe(gulp. dest('dist'))
);

何时用grunt/gulp呢?
若是你的工程模块依赖很是简单,甚至是没有用到模块化的概念。只须要进行简单的合并、压缩,就使用grunt/gulp便可。可是若是整个项目使用了模块化管理,并且相互依赖很是强,咱们就可使用更增强大的webpack了。
因此,grunt/gulp和webpack有什么不一样呢?web

  • grunt/gulp更增强调的是前端流程的自动化,模块化不是它的核心。
  • webpack更增强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能。

webpack的安装

安装webpack首先须要安装Node.js,Node.js自带了软件包管理工具npm。express

cnpm install webpack --save-dev
//--save-dev是开发时依赖,项目打包后不须要继续使用的。

在终端直接执行webpack命令,使用的全局安装的webpack。当在package.json中定义了scripts时,其中包含了webpack命令,那么使用的是局部webpack。npm

webpack的起步

文件和文件夹解析:
dist文件夹:用于存放以后打包的文件
src文件夹:用于存放咱们写的源文件
-----main.js项目的入口 文件。具体内容查看下面详情。
index.html:浏览器打开展现的首页html
package.json:经过npm init生成的,npm包管理的文件(暂时没有用上,后面才会用上)json

js文件的打包

webpack src/main.js dist/bundle.js

使用打包后的文件
打包后会在dist文件下,生成一个bundle.js文件。bundle.js文件,是webpack处理了项目直接文件依赖后生成的一个js文件,咱们只须要将这个js文件在index.html中引入便可

webpack的配置

入口和出口

若是每次使用webpack的命令都须要写上入口和出口做为参数,有一种方法能够将这两个参数写到配置中,在运行时,直接读取。

建立一个webpack.config.js文件
const path = require('path')
module.exports = {
    //入口:能够是字符串/数组/对象,这里咱们入口只有一个,因此写一个字符串便可
    entry:'./src/main.js' ,
    //出口:一般是一个对象,里面至少包含两个重要属性,path 和filename
    output:{
        path: path. resolve(__dirname, 'dist'), //注意: path一般是一 个绝对路径
        filename: 'bundle.js'
    }
}
局部安装webpack

由于一个项目每每依赖特定的webpack版本,全局的版本可能很这个项目的webpack版本不一致,导出打包出现问题。因此一般一个项目,都有本身局部的webpack。

//安装指定本身须要的版本
cnpm install webpack@3.6.0 --save-dev
//启动webpack打包
node_modules/.bin/webpack
package.json中定义启动

咱们能够在package.json的scripts中定义本身的执行脚本。

{
    "name": "meetwebpack",
    "version": "1.0.0",
    "description":"",
    "main": 'index.js',
    "scripts": {
        "build": "'webpack"
    },
    "author":"",
    "license":"ISC",
    "devDependencies": {
        "webpack": "^3. 6. 0"
    }
}

package.json中的scripts的脚本在执行时,会按照必定的顺序寻找命令对应的位置。
首先,会寻找本地的node_modules/.bin路径中对应的命令。若是没有找到,会去全局的环境变量中寻找。

//执行build指令
cnpm run build

loader的使用

什么是loader?
loader是webpack中一个很是核心的概念。在开发中咱们不只仅有基本的js代码处理,咱们也须要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等。对于webpack自己的能力来讲,对于这些转化是不支持的。此时须要给webpack扩展对应的loader。
loader使用过程:
步骤一:经过npm安装须要使用的loader
步骤二:在webpack.config.js中的modules关键字下进行配置
大部分loader咱们均可以在webpack的官网中找到,而且学习对应的用法。loader 的执行顺序是从下到上,从右到左。

css文件处理

须要用到两个loader:css-loaderstyle-loadercss-loader负责加载css文件;style-loader负责将css具体样式嵌入到文档中。
安装

cnpm install --save-dev css-loader style-loader

webpack.config.js中配置

const path = require('path');

module.exports = {
    mode: 'development',
    entry: {
        main: './src/index.js'
    },
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module:{
        rules:[
            { 
                test:/\.css$/, 
                use:['style-loader','css-loader'], 
            }
        ]
    },

}

由于webpack在读取使用的loader的过程当中,是按照从右向左的顺序读取的。因此style-loader须要放在css-loader的前面。

less/scss文件处理

须要安装less 和 less-loader

rules: [{
            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
            }]
        }]

图片文件处理

url-loaderfile-loader
当加载的图片, 小于limit时, 会将图片编译成base64字符串形式.
当加载的图片, 大于limit时, 须要使用file-loader模块进行加载.
修改文件名称
当图片大于limit时,使用file-loader默认会将该图片打包从新命名为32位的hash值放到dist文件夹下。

{
    test: /\.(png|jpg|gif|jpeg)$/,
    use: [
      {
        loader: 'url-loader',
        options: {
          // 当加载的图片, 小于limit时, 会将图片编译成base64字符串形式.
          // 当加载的图片, 大于limit时, 须要使用file-loader模块进行加载.
          limit: 13000,
          // [ext]:表示原始文件名的后缀。[name]:表示原始文件名。[hash:8]:为了防止图片名称冲突,依然使用hash,可是咱们只保留8位
          name: 'img/[name].[hash:8].[ext]'
        },
      }
    ]
},

咱们发现图片并无显示出来,这是由于图片使用的路径不正确。默认状况下,webpack会将生成的路径直接返回给使用者可是,咱们整个程序是打包在dist文件夹下的,因此这里咱们须要在路径下再添加一个dist/

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: 'dist/'
},

babel 的使用

若是但愿将ES6的语法转成ES5,那么就须要使用babel。而在webpack中,咱们直接使用babel对应的loader就能够了。

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

配置webpack.config.js文件

{
    test: /\.js$/,
    // exclude: 排除
    // include: 包含
    exclude: /(node_modules|bower_components)/,
    use: {
      loader: 'babel-loader',
      options: {
        presets: ['es2015']
      }
    }
}

plugin的使用

plugin是插件的意思,一般是用于对某个现有的架构进行扩展。webpack中的插件,就是对webpack现有功能的各类扩展,好比打包优化,文件压缩等等。

loader和plugin区别

loader主要用于转换某些类型的模块,它是一个转换器
plugin是插件,它是对webpack自己的扩展,是一个扩展器

plugin的使用过程:

步骤一:经过npm安装须要使用的plugins(某些webpack已经内置的插件不须要安装)
步骤二:在webpack.config.js中的plugins中配置插件。

添加版权的Plugin

BannerPlugin,属于webpack自带的插件。

const path = require('path')
const webpack = require('webpack')

module.exports = {
  ...
  plugins: [
      new webpack.BannerPlugin('最终版权归aaa全部'),
  ],
}
打包html的plugin

在真实发布项目时,须要将index.html文件打包到dist文件夹中,这个时候就可使用 HtmlWebpackPlugin插件。HtmlWebpackPlugin插件能够为咱们作这些事情:自动生成一个index.html文件(能够指定模板来生成)将打包的js文件,自动经过script标签插入到body中。

npm install html-webpack-plugin --save-dev
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  ...
  plugins: [
      new HtmlWebpackPlugin({
        template: 'index.html'//指定生成Html文件时使用的模板。
      }),
  ],
}

另外,咱们须要删除以前在output中添加的publicPath属性,不然插入的script标签中的src可能会有问题。

CleanWebpackPlugin

CleanWebpackPlugin 会在打包以前删除指定目录下的内容。

npm install clean-webpack-plugin -D

webpack.config.js

const {CleanWebpackPlugin} = require('clean-webpack-plugin'); //注意加{}
module.exports = {
    ...
    plugins:[
        new HtmlWebpackPlugin({
            template: 'src/index.html'
        }), 
        new CleanWebpackPlugin() //不能加参数。
    ],
}

搭建本地服务器

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

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

devserver也是做为webpack中的一个选项,选项自己能够设置以下属性:

`contentBase`:为哪个文件夹提供本地服务,默认是根文件夹,咱们这里要填写./dist
`port`:端口号
`inline`:页面实时刷新
`historyApiFallback`:在SPA页面中,依赖HTML5的history模式
devServer: {
    contentBase: './dist',
    inline: true
}

能够再配置另一个scripts:--open参数表示直接打开浏览器

"scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --open"
},

webpack中配置Vue

el和template区别

在前面的Vue实例中,咱们定义了el属性,用于和index.html中的#app进行绑定,让Vue实例以后能够管理它其中的内容。
这里,咱们能够将div元素中的{{message}}内容删掉,只保留一个基本的id为div的元素
可是若是我依然但愿在其中显示{{message}}的内容,应该怎么处理呢?
咱们能够再定义一个template属性,代码以下:

new Vue({
    el: '#app',
    template: '<div id="app">{{message}}</div>',
    data: {
        message:'coderwhy'
    }
})

el和template模板的关系是什么呢?
el用于指定Vue要管理的DOM,能够帮助解析其中的指令、事件监听等等。
而若是Vue实例中同时指定了template,那么template模板的内容会替换掉挂载的对应el的模板。这样作以后咱们就不须要在之后的开发中再次操做index.html,只须要在template中写入对应的标签便可

稍后会将template模板中的内容进行抽离。会分红三部分书写:templatescriptstyle,结构变得很是清晰。

.vue文件封装处理

main.js

//使用Vue进行开发
import Vue from 'vue'
import App from './vue/App.vue'

new Vue({
  el: '#app',
  template: '<App/>',
  components: {
    App
  }
})

vue-->App.vue

<template>
  <div>
    <h2 class="title">{{message}}</h2>
    <h2>{{name}}</h2>
  </div>
</template>

<script>
  export default {
    name: "App",
    data() {
      return {
        message: 'Hello Webpack',
        name: '张三'
      }
    },
  }
</script>

<style scoped>
  .title {
    color: green;
  }
</style>

安装vue、vue-loader 和 vue-template-compiler 进行处理。

npm install vue-loader vue-template-compiler --save-dev
cnpm install vue --save
module: {
    rules: [
      {
        test: /\.vue$/,
        use: ['vue-loader']
      }
    ]
},
//解决runtime-only版本的Vue报错
resolve: {
    // alias: 别名
    extensions: ['.js', '.css', '.vue'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
}
相关文章
相关标签/搜索