Webpack学习

webpack基础

认识webpack

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

涉及到两个概念:模块 和 打包

模块

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

打包

就是将webpack中的各种资源模块进行打包合并成一个或多个包(Bundle)。并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。

但打包的操作似乎grunt/gulp也可以帮助我们完成,它们有什么不同呢?

和grunt/gulp的对比

grunt/gulp的核心是Task

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

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

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有什么不同呢?

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

webpack的安装

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

cnpm install webpack --save-dev

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

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

webpack的起步

文件和文件夹解析:

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

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

-----main.js项目的入口 文件。具体内容查看下面详情。

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

package.json:通过npm init生成的,npm包管理的文件(暂时没有用上,后面才会用上)

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'

}

}

以上是 Webpack学习 的全部内容, 来源链接: utcz.com/a/15486.html

回到顶部