一、什么是webpack
官方解释
从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具
上述解释,核心就是 模块 和 打包。
前端模块化:webpack中模块化的概念
在学习模块化时,我们了解了一些
目前使用的前端模块化的方案:AMD、CMD、CommonJS、ES6。但是除了ES6浏览器有支持可以直接使用外,其他的必须借助于其他工具,支持我们进行模块化开发,并且通过模块化开发完成了项目,还需要处理模块间的各种依赖,将其进行整合打包。
webpack其中一个核心就是让我们可以进行模块化开发,并且帮助我们处理模块间的依赖关系。
这就是webpack中模块化的概念。
注:webpack中js、css、图片、json文件都可以当作模块使用。
打包如何理解
就是将webpack中的各种资源模块化进行打包合并成一个或多个包(Bundle)。
在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转成css,ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作
webpack打包与grunt/gulp的区别
grunt/gulp
grunt/gulp的核心是Task:通过配置一系列的Task,定义task要处理的事务(ES6、ts转化;图片压缩等),之后依次执行这些task,让整个流程自动化。所以grunt/gulp也被称为前端自动化任务管理工具。
grunt/gulp适用于工程模块依赖非常简单(甚至没有用到模块化的概念)的只需进行简单的合并、压缩的场合。
webpack与grunt/gulp的不同
- grunt/gulp更加强调前端流程的自动化,模块化不是它的核心。
- webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是它附带的功能。
二、webpack安装
webpack的正常运行是依赖于node环境的。node环境依赖各种包,npm是node管理包的工具。
三、webpack的基本使用
1.项目结构:
创建项目时,有两个文件夹,一个是dist文件夹,是打包,发布使用的。一个是src文件夹,主要编码开发用。
2.js文件的打包
-
实际开发中,如果直接在index.html中引入使用模块化的方式进行开发的js文件,是不可以的。因为浏览器不识别其中的模块化代码。并且许多这样的js,一个个引用非常麻烦,且不利于管理。
-
这时就可以使用webpack打包,webpack是一个模块化的打包工具。它可以处理所有模块间的关系,且将多个js文件打包到一个js文件中,这样直接在index.html中直接引用一个js文件就可以了。
-
webpack4打包指令: 加了 -o
webpack .\src\main.js -o .\dist\bundle.js --mode development
webpack '要打包的文件路径' -o '打包保存文件路径' --mode development (模式 开发模式)
3.webpack.config.js和package.json的配置
配置webpack.config.js可以简化打包命令
const path = require('path')
module.exports = {
mode : 'development',
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
}
package.json
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^3.6.0"
}
}
本地安装webpack
npm install webpack@3.6.0 --save-dev
在配置完成后,我们可以在终端中执行“webpack”命令就可以打包了。需要注意的是,在终端中执行webpack命令,执行的都是全局安装的webpack。所以可以在package.json中配置脚本,使得优先寻找本地的webpack。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
配置后,执行下面命令就可以打包了
npm run build
四、loader
loader是webpack中一个非常核心的概念
当我们需要在webpack中加载css、图片,高阶ES6转成ES5代码,TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等时,就需要给webpack扩展对应的loader。
loader使用过程:
- 通过npm安装loader
- 在webpack.config.js中的modules关键字下进行配置。
1.css文件打包
-
安装css-loader和style-loader
//css-loader:只负责将css文件进行加载 //style-loader:负责将样式添加到DOM中 npm install --save-dev css-loader npm install style-loader --save-dev
-
在webpack.config.js中配置
module.exports = { module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] } }
-
在mian.js中导入依赖
require('./css/normal.css')
2.less文件的处理
-
安装less-loader
npm install --save-dev less-loader@4.1.0 less@3.9.0
-
在webpack.config.js中配置,直接写在上面的数组中即可
{ 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 }] }
-
在mian.js中导入依赖
require('./css/speical.less')
3.图片文件处理
-
安装css-loader和style-loader
npm install --save-dev url-loader@1.1.2
-
在webpack.config.js中配置
{ test: /\.(png|jpg|gif|jpeg)$/, use: [ { loader: 'url-loader', options: { limit: 10000, name: 'img/[name].[hash:8].[ext]' } } ] }
limit参数:大小限制
当加载的图片,小于limit时,会将图片编译成base64字符串形式
当加载的图片,大于limit时,需要使用file-loader模块进行加载 且当成模块 需要打包
安装file-loader,file-loader不需要配置,安装即可
npm install file-loader@1.1.11 --save-dev
name参数:图片打包后默认名字是一串hash值,并且是在dist文件夹下,不利于管理查看。这时我们可以使用name属性,对其重新命名,并且放到统一的文件夹中管理。
name: 'img/[name].[hash:8].[ext]'
img文件夹;[name]表示原来的名字;(.)用来拼接;[hash:8]表示生成8位hash值;[ext]表示图片格式。
4.ES6语法处理
目前,有一些浏览器对一些ES6语法还不支持,所以打包js文件时可能需要将ES6语法转成ES5。
-
安装css-loader和style-loader
npm install --save-dev babel-loader@7.1.5 babel-core@6.26.3 babel-preset-es2015@6.24.1
-
在webpack.config.js中配置
{ test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['es2015'] } } }
presets对应一个文件,没有这个文件时,就先使用es2015
五、webpack配置vue
1.安装vue.js(需要将vue当作一个模块,所以通过npm安装)
npm install vue@2.5.21 --save
2.引入依赖
import Vue from 'vue'
3.简单尝试
<div id="app">
<h2>{{message}}</h2>
</div>
import Vue from 'vue';
const app = new Vue({
el: '#app',
data: {
message: 'Hello webpack'
}
});
4.但是打包运行后会报错
webpack-vue.png原因:我们只是安装了runtime-only,不允许有template,代码中div会被当作一个template
vue.png
5.解决方法:在webpack.config.js中添加配置,改变指定的vue文件
resolve: {
//alias:别名
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
6.el和template的区别
真实项目中,我们为了不频繁更改index.html的代码的,所以vue显示的内容可以写在vue实例中的template属性。
new Vue({
el: '#app',
template: `
<div>
<h2>{{message}}</h2>
<button @click="btnClick"></button>
<h2>{{name}}</h2>
</div>
`,
data: {
message: 'Hello webpack',
name: 'codeWhy'
},
methods: {
btnClick() {
}
}
});
在运行后,template属性的内容会替换掉index.html中id为app的div
7.vue的终极使用方案(vue文件封装处理)
-
上面的代码是将vue显示的内容可以写在vue实例中的template属性,但是这样也还不好,还需要进一步的封装。
-
webpack中核心是什么?模块化!既然这样,是不是可以将vue实例中的内容分割出去,当成一个模块。
-
在创建文件时,可以看到有vue component的选项,这个就是工具提供的vue模版
-
接着就可以将显示的内容对应填写,默认导出了
<template> <div> <h2 class="title">{{message}}</h2> <button @click="btnClick">按钮</button> <h2>{{name}}</h2> <Cpn></Cpn> </div> </template> <script> import Cpn from './Cpn.vue' //已经默认导出 export default { name: "app", components: { Cpn }, data() { return { message: 'Hello webpack', name: 'codeWhy' } }, methods: { btnClick() { } } } </script> //这里还可以写css样式 <style scoped> .title { color: green; } </style>
-
在main.js中导入使用即可
import App from './vue/App.vue' new Vue({ el: '#app', template: `<App/>`, components: { App } });
-
注意:在使用时,需要vue-loader
npm install vue-loader@15.4.2 vue-template-compiler@2.5.21 --save-dev
-
配置
{ test: /\.vue$/, use: ['vue-loader'] }
六、认识plugin
plugin是什么:
plugin是插件的意思,通畅用于对某个现有的架构进行扩展
loader和plugin的区别:
loader主要用于转换某些类型的模块,是一个转换器。
plugin是插件,对webpack本身的扩展,是一个扩展器。
使用过程:
1).通过npm安装
2).在webpack.config.js中的plugins中配置
各种plugin
①添加版权的plugin
作用:打包后的文件上方标识代码版权所有者
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.BannerPlugin('最终版权归国家所有')
]
}
②打包html的plugin
目前,我们的index.html文件是放在根目录下的。在我们真是发布项目时的dist文件夹中并没有index.html。所以我们需要将index.html打包到dist文件夹中。这时就可以使用HtmlWebpackPlugin插件。
作用:
自动生成一个index.html文件(可以指定模版)
将打包的js文件自动通过script标签插入到body中
安装HtmlWebpackPlugin插件
npm install html-webpack-plugin@3.2.0 --save-dev
配置
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
}),
]
③js压缩的plugin
作用:将打包的js压缩
安装uglifyjs-webpack-plugin插件
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
配置:开发时不需要,不好调试
plugins: [
new UglifyjsWebpackPlugin(),
]
七、webpack-dev-server搭建本地服务器(打包时不需要)
存在问题:
在开发中,我们不可能每修改次代码就从新打包来看修改后的结果,这样从磁盘中读取信息影响效率。
解决方法:
webpack提供了一个可选的本地开发服务器,基于node.js搭建,内部是express框架,使浏览器可以自动刷新显示我们修改后结果。从而使得我们可以在确认无误后只打一次包。
它是一个单独的模块,使用前也需要安装
npm install --save-dev webpack-dev-server@2.9.1
配置webpack.config.js
module.exports = {
devServer: {
contentBase: './dist',(为那一个文件夹提供本地服务,默认根文件,我们需填上打包指定文件夹)
inline: true,(页面实时刷新)
port(可以指定端口号,默认8080)
}
}
还需在package.json文件中配置启动脚本
"dev": "webpack-dev-server"
配置后在终端中使用下面的命令即可开启服务
npm run dev
补充:
配置脚本还可以写成("dev": "webpack-dev-server --open"),添加--open后缀,意思是可以在启动服务时,自动打开网页。
八、配置文件的分离
在webpack.config.js配置文件中,有些是开发时的配置(webpack-dev-server),有的是编译时的配置(uglifyjs-webpack-plugin)。如果都放在一起的话不利于管理。所以我们接下来可以将配置文件进行分离操作。
需要安装webpack-merge:可以对配置文件进行合并
npm install webpack-merge@4.1.5 --save-dev
要达成下图中的效果:将一个文件分成三个文件
配置分离.png原文件:webpack.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'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.css$/,
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|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new webpack.BannerPlugin('最终版权归国家所有'),
new HtmlWebpackPlugin({
template: 'index.html'
}),
new UglifyjsWebpackPlugin(),
],
devServer: {
contentBase: './dist',
inline: true
}
}
将开发时需要的配置抽出:使用webpackMerge可以和公共的配置合并 dev.config.js
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');
module.exports = webpackMerge(baseConfig, {
devServer: {
contentBase: './dist',
inline: true
}
})
将打包时需要的配置抽出:使用webpackMerge可以和公共的配置合并 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(),
],
})
整理公共配置: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'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.css$/,
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|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
//alias:别名
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new webpack.BannerPlugin('最终版权归国家所有'),
new HtmlWebpackPlugin({
template: 'index.html'
}),
],
}
网友评论