您的位置:首页 > Web前端 > Webpack

webpack初步了解

2018-03-12 16:31 477 查看

webpack初步了解

webpack初步了解
构建工具
构建工具的功能

常用的构建工具

webpack介绍
webpack命令

webpack常用配置介绍
出入口 Entry&Output
entry配置

output的配置

模块 Module

模块加载(转换)器 Loader

loader学习
使用loader的三种方式

babel

插件 Plugin

webpack-dev-server
devServer配置项

webpack插件
extract-text-webpack-plugin

开发/生产环境打包

webpack项目中的最佳配置

构建工具

构建工具的功能

代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。

文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等。

模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。

代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。

自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。

代码校验:在代码被提交到仓库前需要校验代码是否符合规范,以及单元测试是否通过。

常用的构建工具

grunt

gulp

fis3(百度)

webpack模块化管理工具,可以对模块进行:

压缩

预处理

按需打包

按需加载

热加载

webpack介绍

webpack可以看做是模块打包机,它做的事情是:

分析你的项目结构,找到JavaScript模块;

其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等);

并将其转换和打包为合适的格式供浏览器使用;

4000
Webpack和Grunt以及Gulp相比有什么特性

Webpack和另外两个并没有太多的可比性;

Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案;

Webpack的优点使得Webpack在很多场景下可以替代Gulp/Grunt类的工具;

Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。

Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。

webpack特征

插件化:webpack本身非常灵活,提供了丰富的插件接口。基于这些接口,webpack开发了很多插件作为内置功能

速度快:webpack使用异步IO以及多级缓存机制。所以webpack的速度是很快的,尤其是增量更新。

丰富的Loaders:loaders用来对文件做预处理。这样webpack就可以打包任何静态文件。

高适配性:webpack同时支持AMD/CommonJs/ES6模块方案。webpack会静态解析你的代码,自动帮你管理他们的依赖关系。此外,webpack对第三方库的兼容性很好。

代码拆分:webpack可以将你的代码分片,从而实现按需打包。这种机制可以保证页面只加载需要的JS代码,减少首次请求的时间。

优化:webpack提供了很多优化机制来减少打包输出的文件大小,不仅如此,它还提供了hash机制,来解决浏览器缓存问题。

开发模式友好:webpack为开发模式也提供了很多辅助功能。比如SourceMap、热更新等。

使用场景多:webpack不仅适用于web应用场景,也适用于Webworkers、Node.js场景

webpack命令

webpack 执行一次开发时的编译

webpack -p 执行一次生成环境的编译(压缩)

webpack –watch 在开发时持续监控增量编译(很快)

webpack -d 让他生成SourceMaps

webpack –progress 显示编译进度

webpack –colors 显示静态资源的颜色

webpack –display-chunks 展示编译后的分块

webpack –display-modules 列出打包模块

webpack –display-reasons 显示更多引用模块原因

webapck –display-error-details 显示更多报错信息

webpack常用配置介绍

出入口 Entry&Output

entry:入口

关联的很多其他需要打包的文件

output:出口

path:文件打出的路径,这个path是nodejs内置的方法;

entry和output配置

entry配置

entry是指需要打包的文件;

entry有几种使用方法:

字符串

entry:__dirname+'/src/script/main.js'
//对应
output:{
path:__dirname+'/dist/js',
filename:'bundle.js'
}


数组

entry:[
__dirname+'/src/script/main.js',
__dirname+'/src/script/a.js'
]
//对应
output:{
path:__dirname+'/dist/js',
filename:'bundle.js'
}


对象

entry:{
main:__dirname+'/src/script/main.js',
a:__dirname+'/src/script/a.js'
}
//对应
output:{
path:__dirname+'/dist/js',
filename:'[name]-[hash].js'
}
//or
output:{path:__dirname+'/dist/js',filename:'[name]-[chunkhash].js'}


output的配置

output是指打包生成的文件

entry中输入多个chunk时,为确保文件名唯一避免相互覆盖使用占位符命名filename;

三种占位符

[name]是chunk的name;

[hash]是本次打包的hash值,hash值相同;

[chunkhash]是每个chunk的hash值,不同文件同次打包不相同,保证文件的唯一性,只有改变文件中的内容时hash才变化,未做改变的文件hash值不变;

模块 Module

module:模块,在 Webpack眼里一切皆模块,默认只识别js文件, 如果是其它类型文件利用对应的loader转换为js模块。

rules:做很多的规定,比如:加载css、将es6编译成es5;

“-loader”其实是可以省略不写的,多个loader之间用“!”连接起来

module: {
//加载器配置
loaders: [
//.css 文件使用 style-loader 和 css-loader 来处理
{ test: /\.css$/, loader: 'style-loader!css-loader' },
//.js 文件使用 jsx-loader 来编译处理
{ test: /\.js$/, loader: 'jsx-loader?harmony' },
//.scss 文件使用 style-loader、css-loader 和 sass-loader 来编译处理
{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
//图片文件使用 url-loader 来处理,小于8kb的直接转为base64
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
]
}


webpack本身只能加载js模块,如果需要加载其他类型的文件(模块),就需要使用对应的loader进行转换/加载;

如果我们想要在js文件中通过require引入模块,比如css或image,那么就需要在这里配置加载器,这一点对于React来说相当方便,因为可以在组件中使用模块化CSS。而一般的项目中可以不用到这个加载器。

module 的作用是添加loaders, 那loaders有什么作用呢?

模块加载(转换)器 Loader

loader:模块加载器,将非js模块包装成webpack能理解的js模块;

loader用于转换应用程序的资源文件。他们是运行在nodejs下的函数,使用参数来获取一个资源的来源,并且返回一个新的来源(资源的位置)。

文件loader:

url-loader 像 file loader 一样工作,但如果文件小于限制,可以返回 data URL

file-loader 将文件发送到输出文件夹,并返回(相对)URL

JSON的loader

json-loader 加载 JSON 文件(默认包含)

ES5-6的loader

babel-loader 加载 ES2015+ 代码,然后使用 Babel 转译为 ES5

css的loader

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

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

less-loader 加载和转译 LESS 文件

sass-loader 加载和转译 SASS/SCSS 文件

stylus-loader 加载和转译 Stylus 文件

代码规范loader

eslint-loader PreLoader,使用 ESLint 清理代码

vue的loader

vue-loader 加载和转译 Vue 组件

resolve

alias可以用于定义别名,用过seajs等模块工具的都知道alias的作用,比如我们在这里定义了ui这个别名,那么在模块中想引用ui目录下的文件,就可以直接这样写:
require('ui/dialog.js');
不用加上前面的更长的文件路径。

resolve: {
//查找module的话从这里开始查找
root: 'E:/github/flux-example/src', //绝对路径
//自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
extensions: ['', '.js', '.json', '.scss'],
//模块别名定义,方便后续直接引用别名,无须多写长长的地址
alias: {
AppStore : 'js/stores/AppStores.js',//后续直接 require('AppStore') 即可
ActionType : 'js/actions/ActionType.js',
AppAction : 'js/actions/AppAction.js'
}
}


loader学习

学习网址:https://webpack.js.org/concepts/loaders/

Webpack 本身只能处理原生的js模块,但是loader转换器可以将各种类型的资源转换成js模块。这样,任何资源都可以成为Webpack可以处理的模块。

使用loader的三种方式

在文件中直接引入loader文件,es6的语法

//es6的语法
import Styles from 'style-loader!css-loader?modules!./styles.css';
//commonjs语法
require('style-loader!css-loader?modules!./styles.css')


在命令行界面使用的方式CLI

//直接执行
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'


在配置文件中使用loader

module: {
rules: [
{
<!-- 首先对资源一个正则匹配 -->
test: /\.css$/,
<!-- 匹配成功后会使用多个loader对其进行处理 -->
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}


babel

Babel通过语法转换器支持最新版本的JavaScript。这些插件允许你立刻使用新语法,无需等待浏览器支持。

在src文件夹下创建component文件夹,component里面创建layer组件,组件里有js、css、html文件;

在src文件夹中创建入口js文件,app.js;

//app.js中引入html
import layer from './component/layer/layer.js'
const App = function() {
console.log(layer)
}
new App()

//layer.js中渲染模板
import tpl from './layer.html'
function layer() {
return {
name: 'layer',
tpl: tpl
}
}
export default layer;


安装babel转化es6的代码
npm install --save-dev babel-loader babel-core
(webpack3版本)

使用babel加载器将es6的语法进行转化,转化时要指定参数,方式有三种:

使用配置指定

//在配置webpack.config.js中添加
module: {
rules: [{
test: /\.js$/,
loader: "babel-loader",
//加快打包速度的配置
//排除范围
exclude: __dirname + '/node_modules/',
//babel-loader的处理范围
include: '/src/',
//webpack3中使用options代替query
options: {
'presets': ['env']
}
}]
}


在package.json中添加

"babel":{
"presets":["env"];
}


根目录下创建.babelrc文件

{
"presets": ["env"]
}


插件 Plugin

plugin:插件,在webpack构建流程中的特定时机插入具有特定功能的代码;



//使用了CommonsChunkPlugin用于生成公用代码,不只可以生成一个,还能根据不同页面的文件关系,自由生成多个,例如:
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
entry: {
p1: "./page1",
p2: "./page2",
p3: "./page3",
ap1: "./admin/page1",
ap2: "./admin/page2"
},
output: {
filename: "[name].js"
},
plugins: [
new CommonsChunkPlugin("admin-commons.js", ["ap1", "ap2"]),
new CommonsChunkPlugin("commons.js", ["p1", "p2", "admin-commons.js"])
]
};
// 在不同页面用<script>标签引
e44d
入如下js:
// page1.html: commons.js, p1.js
// page2.html: commons.js, p2.js
// page3.html: p3.js
// admin-page1.html: commons.js, admin-commons.js, ap1.js
// admin-page2.html: commons.js, admin-commons.js, ap2.js


例:

module.exports = {
devtool: "source-map",    //生成sourcemap,便于开发调试
entry: getEntry(),         //获取项目入口js文件
output: {
path: path.join(__dirname, "dist/js/"), //文件输出目录
publicPath: "dist/js/",        //用于配置文件发布路径,如CDN或本地服务器
filename: "[name].js",        //根据入口文件输出的对应多个文件名
},
module: {
//各种加载器,即让各种文件格式可用require引用
loaders: [
// { test: /\.css$/, loader: "style-loader!css-loader"},
// { test: /\.less$/, loader: "style-loader!csss-loader!less-loader"}
]
},
resolve: {
//配置别名,在项目中可缩减引用路径
alias: {
jquery: srcDir + "/js/lib/jquery.min.js",
core: srcDir + "/js/core",
ui: srcDir + "/js/ui"
}
},
plugins: [
//提供全局的变量,在模块中使用无需用require引入
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery",
// nie: "nie"
}),
//将公共代码抽离出来合并为一个文件
new CommonsChunkPlugin('common.js'),
//js文件的压缩
new uglifyJsPlugin({
compress: {
warnings: false
}
})
]
};


webpack-dev-server

webpack-dev-server是一个轻量级的服务器,修改文件源码后,自动刷新页面将修改同步到页面上;

webpack-dev-server的他爹和他爹的朋友

webpack-dev-middleware:作为一个 webpack 中间件,它会开启 watch mode 监听文件变更,并自动地在内存中快速地重新打包、提供新的 bundle,自动编译(watch mode)+速度快(全部走内存)。

webpack-hot-middleware:

webpack 可以通过配置 webpack.HotModuleReplacementPlugin 插件来开启全局的 HMR 能力;

开启后 bundle 文件会变大一些,因为它加入了一个小型的 HMR 运行时(runtime),当你的应用在运行的时候,webpack 监听到文件变更并重新打包模块时,HMR 会判断这些模块是否接受 update,若允许,则发信号通知应用进行热替换。

webpack-dev-server是一个小型的Node.js Express服务器,它使用webpack-dev-middleware来服务于webpack的包,除此自外,它还有一个通过Sock.js来连接到服务器的微型运行时

webpack-dev-server是一个独立的NPM包,你可以通过npm install webpack-dev-server来安装它。

webpack-dev-server配置

var WebpackDevServer = require("webpack-dev-server");
var webpack = require("webpack");

var compiler = webpack({});
var server = new WebpackDevServer(compiler, {

contentBase: "/path/to/directory",

hot: true,

historyApiFallback: false,

compress: true,

proxy: {
"**": "http://localhost:9090"
},
setup: function(app) {},
staticOptions: {},
quiet: false,
noInfo: false,
lazy: true,
filename: "bundle.js",
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
publicPath: "/assets/",
headers: { "X-Custom-Header": "yes" },
stats: { colors: true }
});
server.listen(8080, "localhost", function() {});


devServer配置项

contentBase

即 SERVERROOT,如 “path.join(__dirname, “src/html”)”,后续访问 http://localhost:3333/index.html 时,SERVER 会从 src/html 下去查找 index.html 文件。

它可以是单个或多个地址的形式:(若不填写该项,默认为项目根目录。)

//单个
contentBase: path.join(__dirname, "public")
//多个:
contentBase: [path.join(__dirname, "public"), path.join(__dirname, "assets")]


port

即监听端口,默认为8080。

compress

传入一个 boolean 值,通知 SERVER 是否启用 gzip。

hot

传入一个 boolean 值,通知 SERVER 是否启用 HMR。

https

可以传入 true 来支持 https 访问,也支持传入自定义的证书:

https: true
//也可以传入一个对象,来支持自定义证书
https: {
key: fs.readFileSync("/path/to/server.key"),
cert: fs.readFileSync("/path/to/server.crt"),
ca: fs.readFileSync("/path/to/ca.pem"),
}


proxy

代理配置,适用场景是,除了 webpack-dev-server 的 SERVER(SERVER A) 之外,还有另一个在运行的 SERVER(SERVER B),而我们希望能通过 SERVER A 的相对路径来访问到 SERVER B 上的东西。

devServer: {
contentBase: path.join(__dirname, "src/html"),
port: 3333,
hot: true,
proxy: {
"/api": "http://localhost:5050"
}
}
//运行 webpack-dev-server 后,若访问 http://localhost:3333/api/user,则相当于访问 http://localhost:5050/api/user。


publicPath

如同 webpack-dev-middleware 的 publicPath 一样,表示从内存中的哪个路径去存放和检索静态文件;

不过官方文档有一处错误需要堪正 —— 当没有配置 devServer.publicPath 时,默认的 devServer.publicPath 并非根目录,而是 output.publicPath;

这也是为何咱们的例子里压根没写 devServer.publicPath,但还能正常请求到 https://localhost:3333/assets/bundle.js

setup

webpack-dev-server 的服务应用层使用了 express,故可以通过 express app 的能力来模拟数据回包,devServer.setup 方法就是干这事的:

devServer: {
contentBase: path.join(__dirname, "src/html"),
port: 3333,
hot: true,
setup(app){  //模拟数据
app.get('/getJSON', function(req, res) {
res.json({ name: 'vajoy' });
});
}
}


webpack插件

webpack 通过 plugins 实现各种功能。常见的 plugins 如下:

webpack.DefinePlugin 定义环境变量;

const webpack = require('webpack');
const NODE_ENV = process.env.NODE_ENV; // 从命令行环境获取 NODE_ENV 参数
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify(NODE_ENV)
} // 定义浏览器中的替换的变量为 `process.env.NODE_ENV`
})
]
}


webpack.EnvironmentPlugin 定义环境变量;

const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.EnvironmentPlugin([
'NODE_ENV'
])
]
}


webpack.optimize.CommonsChunkPlugin 共用 js 打包

html-webpack-plugin 使用模版生成 html 文件

webpack-visualizer-plugin 输出依赖文件分析图表

webpack.HotModuleReplacementPlugin 代码热更新,用于调试模式

webpack.optimize.OccurrenceOrderPlugin 调整模块的打包顺序,用到次数更多的会出现在文件的前面

webpack.NoErrorsPlugin 构建过程中有报错,不认为构建完成

webpack.ProgressPlugin 输出构建进度

webpack.BannerPlugin 在文件头添加注释

webpack.optimize.UglifyJsPlugin 压缩 js

webpack.optimize.DedupePlugin 去除重复依赖

extract-text-webpack-plugin 从 js 中提取出样式文件,单独打包成 css 文件;

clean-webpack-plugin每次运行清除指定目录下打包文件;

extract-text-webpack-plugin

作用:该插件的主要是为了抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象;

安装:
npm install extract-text-webpack-plugin --save-dev


插件参数:

use:指需要什么样的loader去编译文件,这里由于源文件是.css所以选择css-loader

fallback:编译后用什么loader来提取css文件

publicfile:用来覆盖项目路径,生成该css文件的文件路径

使用:

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader", // 编译后用什么loader来提取css文件
use: "css-loader" // 指需要什么样的loader去编译文件,这里由于源文件是.css所以选择css-loader
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
}


开发/生产环境打包

webpack.base.conf.js

开启source Map ,帮助调试

webpack项目中的最佳配置

webpack官方提供的配置方法是通过module.exports返回一个json,但是这种场景不灵活,不能适配多种场景。

比如要解决:production模式和development模式,webpack的配置是有差异的,大致有两种思路。

1、两份配置文件
webpack.config.production.js/webpack.config.development.js
,然后不同场景下,使用不同的配置文件。

2、通过module.exports返回函数,该函数能接受参数。

相对来说,第一种更简单,但是重复配置多;第二种更灵活,推荐第二种方式。

//返回函数的方式的配置代码架子如下:
module.exports = function(env) {
return {
//上下文
context: config.context,
//入口文件,是所有依赖关系的入口,webpack从这个入口开始静态解析,分析模块之间的依赖关系。
entry: config.src,
//打包输出的配置
output: {
path: path.join(config.jsDest, project),
filename: '[name].js',
chunkFilename: '[name].[chunkhash:8].js',
publicPath: '/assets/' + project + '/'
},
//SourceMap选项,便于开发模式下调试。
devtool: "eval",
//监听模式,增量更新,开发必备!
watch: false,
//优化。
profile: true,
//webpack构建的过程中会生成很多临时的文件,打开cache可以让这些临时的文件缓存起来,从而更快的构建。
cache: true,
//loaders用来对文件做预处理。这样webpack就可以打包任何静态文件。
module: {
loaders: getLoaders(env)
},
//模块别名,这样可以更方便的引用模块。
resolve: {
alias: getAlias(env)
},
//webpack的一些内置功能均是以插件的形式提供。
plugins: getPlugins(env)
};
}


gitHub参考地址:https://github.com/mutouafangzi/webpackDemo20180222
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: