webpack学习

1.什么是webpack?

从本质上来讲,webpack是一个现代的Javascript应用的静态模块化打包工具。

这里的关键点就是模块打包

1.1前端模块化

(1)在这之前大家已经知道了在前端开发中为什么要进行模块化开发,目前使用的前端模块化方案有:AMD、CMD、CommonJs、ES6。

(2)在ES6之前我们要想进行模块化开发,必须借助于其他的工具,让我们可以进行模块化开发。并且在模块化开发完成后,我们还需要处理各种模块之间的依赖关系,并且将他们进行整合打包。

(3)而webpack其中一个核心就是让我们可以进行模块化开发,并且会帮助我们处理模块之间的依赖关系。

(4)在这里不仅仅是Javascript文件,我们的css、图片、json文件等再webpack中都可以被当做模块来使用,这就是webpack模块化的概念。

1.2打包

(1)打包这个概念比较好理解了,就是利用webpack将各种资源进行打包合并为一个或者多个包(bundle)。在打包过程中,还可以对资源进行处理,比如压图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成Javascript等等操作。

(2)在这里我们会想到,gulp也可以进行资源的打包,那么它和webpack有什么区别呢?

*webpack和grunt/gulp对比

(1)grunt/gulp的核心是Task

我们可以配置一系列的task,并且定义task需要处理的事务(例如ES6转ES5,ts转化,图片压缩,scss转成css),之后让grunt/gulp来执行这些task,而且让整个流程自动化,所以grunt/gulp也被称为前端自动化任务管理工具

(2)什么时候用grunt/gulp呢?

如果你的项目模块依赖非常简单,或者是没有用到模块化的概念,只需要进行简单的合并和压缩,就使用grunt/gulp即可。但是如果整个项目使用了模块化管理,而且相互之间依赖非常强,我们就可以使用更加强大的webpack了。

(3)所以webpack和grunt/gulp有什么不同呢?

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

* webpack更加强调模块化开发管理,而文件压缩合并,预处理等功能,是他附带的功能。

2.webpack的安装

* webpack为了可以正常运行必须依赖node环境。node自带了包管理工具(npm)。

执行指令:npm install [email protected] -g 进行全局安装。这里指定了下载3.6.0的版本。

(1)为什么全局安装后还需要局部安装呢?

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

3.webpack的基本使用

(1)在webpack打包中一般目录结构:

src(源码):用于存放我们的源文件

        main.js: 项目的入口文件(这里有时候也可以命名为index.js)。

        aaa.js定义了一些函数,可以在其他地方引用,并且使用。

dist(distribution发布):用于存放之后打包的文件。

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

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

(2)在src文件下我们写的东西都可通过模块化的方式去实现(AMD/CMD/CommonJs/ES6都可以)。

用CommonJs模块化进行模块化开发

CommonJs方式导出:module.exports = {}  

在入口文件main.js导入:const {add , mul} = require('./aaa.js');

用ES6的模块化进行模块开发

ES6方式导出:export const name = '库里';

                           export const age = 18;

在入口文件main.js中导入: import {name, age} from './info.js'

这个时候只需要用webpack打包一下,它会自动的帮我们处理模块之间相互之间的依赖,处理完成后它会生成一个最终的js文件(bundle.js),我们在引用的时候只需要用最终生成的那个js文件就可以了。

4.webpack.config.js和package.json的配置

(1)配置webpack.config.js文件:

const path = require('path');  // 这里需要用到node里面的path模块,这里用到的是node里面的相关的包(执行npm init,生成一个package.json文件,这个文件是告诉我们项目中的一些相关信息的)。

* 当package.json中依赖相关东西的话,我们需要执行npm install,会根据里面所有的依赖帮助我们安装一些所需要的东西。

module.exports= {

    entry: ' ./src/main.js ',  // 入口文件

    output: {  // 出口文件

        path: path.resolve(_dirname, 'dist'),  // 这里要动态获取一个绝对路径,这里引用到了一个path模块中的resolve函数,用来对我们两个路径拼接(_dirname这里对这个上下文变量进行拼接)。

        filename: ' bundle.js '

    }

}

当我们在webpack.config.js中进行了以上配置后,我们就可以在终端直接执行webpack命令实现对项目的打包。

(2)如何用npm run build 命令替代webpack命令执行打包效果?

这里还需要把二者进行一个映射:

打开package.json,对文件中scripts进行配置

"scripts": {

    "build": webpack

}

* 开发时依赖(这就是在本地安装webpack要加--save-dev的原因,因为webpack只有在开发时需要,打包上传到服务器后就没用了)

*运行时依赖

前面有说到除了全局安装一个webpack之外,我们还要在本地安装一个webpack。执行npm install [email protected] --save-dev。

* 在终端中敲命令时,用到的webpack都是全局的,但是当我们在package.json中定义scripts脚本时,然后执行npm run build,此时用到的就是本地的webpack。

5.什么是loader?

laoder在webpack中是一个非常核心的概念。在开发中我们不仅仅有基本的js代码处理,也需要加载css、图片ES6的转化,以及将.vue文件转成js文件等等,对于webpack本身的能力来说,对于这些转化是不支持的,这时候就需要用到loader解决。

loader使用过程:

(1)通过npm安装需要使用的loader

(2)在webpack.config.js中的modules关键字下面进行配置

5.1webpack中css文件的配置

安装style-loader: npm install style-loader --save-dev

* 注意:style-loader要放在css-loader前面,为什么呢?因为webpack在读取使用loader的过程中,是按照从右向左顺序读取的。负责将样式添加到DOM中

安装css-loader: npm install css-loader --save-dev   

* 这里如果只引入css-loader会发现样式没有生效,这是因为css-loader只负责加载css文件,但是并不负责将css具体样式嵌入到文档中,这个时候我们还需要引入一个style-laoder。

在webpack.config.js中进行配置(具体参考wabpack的官方文档:https://www.webpackjs.com/)

module: {

    rules: [

        {

            test: /\.css$/,

            use: [ ' style-loader ' , ' css-loader ' ]

        }

    ]

}

5.2less文件处理

安装less-loader: npm install less-loader less --save-dev

* 通过less加载对应的less文件,下载同时还会下载一个less的包,可以对less文件的相关代码进行一个解析。

webpack.config.js中配置如下:

module: {

    rules: [

        {

            test: /\.css$/,

            use: [ ' style-loader ' , ' css-loader ' , 'less-loader']   // 这里也可以用对象的形式比如:loader:'style-loader'

        }

    ]

}

5.3webpack图片文件的处理

安装url-loader: npm install --save-dev url-loader

* 当我们需要加载比limit大的图片时,我们需要下载file-loader。

安装file-loader: npm install --save-dev file-loader

webpack.config.js中配置如下:

module: {

    rules: [

        {

            test: /\.(png|jpg|jpeg|gif)$/,

            use: [

                {

                    loader: 'url-loader',

                    options: {

                        limit: 8192

                        * 当加载的图片小于limit时,会将图片编译成base64字符串形式。

                        * 当加载的图片大于limit时,需要使用file-loader模块进行加载。

                    }

                }

            ]

        }

    ]

}

* 我们发现,在图片打包的时候webpack自动帮助我们生成了一个非常长的名字,这是一个32位的hash值,目的就是防止名字重复,但是实际开发中我们对名字也有一定的要求,比如讲所有的图片放在一个文件夹中,跟上原来图片的名称,同时还要防止重复。

所以我们可以在options中添加上如下选项:

img: 文件要打包到的文件夹

name: 获取图片原来的名字,放在该位置。

hash:8  为了防止图片名称冲突,依然使用hash,但是只保留8位数。

ext: 使用图片原来的扩展名

例子: name: 'img/[name].[hash:8].[ext]';

5.4 ES6转ES5的babel

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

*在webpack中,ES6转ES5需要使用对应的loader,这时候就需要下载babel-loader

webpack.config.js中配置如下:

module: {

    rules: [

        {

            test: /\.js$/,

            exclude: /(node_modules|bower_components)/, // 排除

            use: [

                {

                    loader: 'babel-loader',

                    options: {

                        presets: ['@babel/preset-env']

                    }

                }

            ]

        }

    ]

}

5.5 webpack中vue配置过程

runtime-only // 这种版本代码中不可以有任何的templete

runtime-compiler // 这种版本代码中可以有template,因为有compiler可以用于编译template

过程:

(1)安装vue: npm install --save vue

(2)引入 import Vue from 'vue'

(3)由于vue版本不太对(runtime-only/runtime-complier),通过alias(别名)解决版本错误。

vue对应loader安装: npm install vue-loader vue-template-compiler --save-dev

webpack.config.js中配置如下:

module: {

    rules: [

        {

            test: /\.vue$/,

            use: [

                {

                    loader: 'vue-loader',

4              }

            ]

        }

    ]

}

* package.json中的内容修改后都要执行一下npm install重新做一下安装

5.6 el和template的区别

* 当你定义了一个template属性,此时又有el属性挂载,这时候template定义的东西会替换掉el属性所挂载的所有代码

6. webpack-认识plugin(插件)

* plugin是插件的意思,通常用于对现有的框架进行扩展。

*webpack中的插件,就是对webpack现有的功能进行各种扩展,比如打包优化,文件压缩等等。

*loader和plugin的区别: loader用于转换某些类型的模块它是一个转换器。plugin是插件,它是对webpack本身的扩展,是一个扩展器。

*plugin使用过程:

通过npm安装需要使用的plugin,在webpack.config.js中配置插件。

(1)BannerPlugin的使用,添加版权信息

plugins: [

    new wabpack.BannerPlugin('最终版权归我所有')

]

(2)HtmlWebpackPlugin的使用

* 把根目录下的index.html打包到dist文件中

* 这个插件可以自动生成一个index.html文件(可以指定模板来生成),将打包的js文件,自动通过script标签插入到body中

安装:npm install html-webpack-plugin --save-dev

配置webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');  // 导入

plugins: [

    new wabpack.BannerPlugin('最终版权归我所有'),

    new HtmlWebpackPlugin({

        template: 'index.html',  // 这里是可以指定模板的,指定某一个模板作为dist文件中生成的html文件的模板。

    })

]

(3)UglifyjsWebpackPlugin的使用

* 对打包的js文件进行丑化压缩的插件

* 我们使用一个第三方的插件uglifyjs-webpack-plugin,并且版本号指定1.1.1,和cli2保持一致

安装: npm install [email protected] --save-dev

配置webpack.config.js:

const UglifyjsWebpackPlugin = require('html-webpack-plugin');  // 导入

plugins: [

    new wabpack.BannerPlugin('最终版权归我所有'),

    new HtmlWebpackPlugin(),

    new UglifyjsWebpackPlugin(),

]

7.搭建本地服务器

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

它是一个单独的模块,在webpack中使用它需要先安装:

npm install --save-dev [email protected]

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

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

port: 端口号

inline: 页面实时刷新

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

配置webpack.config.js:

devServer: {

    contentBase: './dist',

    inline: true

}

开发时执行脚本可以在package.json中加入'dev': 'weback-dev-server  --open',这时候执行npm run dev就可以启动本地服务器,加入--open可以实现执行命令自动打开浏览器。

* 开发阶段不要加入UglifyjsWebpackPlugin插件,在发布阶段再加入,因为丑化了js文件后,调试阶段不好阅读

8.webpack配置文件的分离

* 有的配置是需要打包时候使用,比如说丑化js等等,有的配置是需要本地开发时候使用,比如说配置本地服务器。这里就需要把webpack配置进行一个分离,根据开发时候的配置和发布时候的配置。

这时候需要把以前的webpack.config.js分成三个不同的js,这三个不同的js放在根目录下的build文件夹中分别是:

base.config.js :  里面存放的是一些公共的配置

prod.config.js :生产环境的一些配置

dev.config.js : 开发环境的一些配置

这么分的思路就是我们把开发和生产环境的配置实现一个分离,这时候需要安装一个webpack-merge的模块,它的作用是把base和prod,base和dev,分别合并,这样就实现了开发和生产环境配置的分离。

安装: npm install webpack-merge --save-dev

prod和base合并:

在prod.config.js中:

const baseConfig = require('./base.config.js');

module.exports = { baseConfig,{

    plugins: [

        new UglifyjsWebpackPlugin(),

    ]

})

在dev.config.js中:

const baseConfig = require('./base.config.js');

module.exports = { baseConfig,{

    devServer: {

        contentBase: './dist',

        inline: true

    }

})

但是这时候你要是执行npm run build是会报错的,因为我们现在已经把webpack.config.js删了,这时候我们就需要在package.json中指定一下用哪个配置文件:

"scripts": {

    "build": ‘webpack --config ./build/prod.config.js',

    "dev": 'webpack-dev-server --open --config ./build/dev.config.js'

}

这时候就可以正常打包了,但是此时打包完成的dist文件是加到了build文件夹中,这个是因为我们在base.config.js中出口output拼接的目录路径错误,修改一下目录就可以了。

你可能感兴趣的:(webpack学习)