在学习 Webpack 以前,咱们须要了解一个概念:模块。javascript
若是你曾学过 Java , C# 之类的语言,必定会知道 Java 中的 import 或 C# 中的 using 吧?css
好比:我想在 C# 中进行数据库操做,我只须要在代码头部加上 下面这两段代码便可。html
using System.Data; using System.Data.SqlClient;
这两段代码能够当作 两个与数据库操做相关的模块。 当咱们需求是数据库,或者是读取 IO 等其余操做,咱们便加载其余不一样的模块。前端
很明显,这实现了编程中的一个很是重要的功能 按需加载。java
在前端中 模块又该如何定义呢? 按照我我的的理解:jquery
<div class="layer"> <div><%= name %></div> <% for(var i = 0; i < People.length;++i) { %> <%= People[i] %> <% } %> </div>
header{ display:block; } header h1{ font-size: 60px; }
let People = { name: "Simon" } ; module.exports = People;
而咱们又该怎样实现 在前端中加载模块呢?webpack
下面是两个很常见的例子:git
在 Less 中es6
@import "header"; @import "layout"; @import "footer";
在 Javascriptgithub
// CommonJS const $ = require("jQuery"); //es6 let People = { name: "Simon" } ; module.exports = People; import "./layer.less"; import tpl from "./layer.ejs";
若是你直接运行以上代码,浏览器并不会解析,这个时候,就要依靠 Webpack 了!
Webpack 是一款目前很是流行的前端模块打包工具,能够将项目中所加载的模块进行打包,以及将 一些浏览器不支持的语言进行转换。
Webpack 的打包原理是 先找到入口文件,递归探索出全部依赖的模块,最后 利用 Loader 进行不一样文件类型的处理,打包成一个 Javascript 文件。
其中,Webpack 的两个最核心原理分别是:
固然 Webpack 的做用不止加载模块这么简单,前端的经常使用需求一般均可以实现:利用 Loader 转换 es6 、 Less 、 Typescript ,还可利用插件 开发多页面应用,等等诸多强大功能。
下面,我将讲解 Webpack 的具体使用和配置。
我通常在项目中使用 Webpack,都是先执行下面这四条命令进行 Webpack 的安装
npm install -g webpack
在全局安装 Webpack,第一次使用时 执行
npm install --save-dev webpack
将 Webpack 安装到你的项目
npm init
npm初始化,会询问你的项目信息,能够回车跳过
npm install --save-dev webpack-dev-server
在当前项目,安装 Webpack 服务器
安装完成后,即是创建配置文件了。
在项目根目录下新建名为 webpack.config.js 的文件,
基本上 一个配置文件的大致结构就是下面这样:
modules.export={ entry:{ /* 入口文件 */ }, output:{ /* 出口文件 */ }, module:{ /* Loader */ rules:[{},{},{}] }, plugins:[ /* 插件 */ ], devtool: ... devServer: {...} resolve:{...} }
咱们下面就先分析 modules.export 各个属性
entry 表明是入口文件,Webpack 工做的开始。
Webpack 会递归的探索出 入口文件中所依赖的模块,并按照顺序 利用 Loader 进行处理。
官网给出了其 3 种数据类型:
entry: "app.js";
数组
数组中的每一项都会被打包,造成互不依赖的文件
entry: ["app.js","main.js"];
对象
对象中的每个属性都会被打包,造成互不依赖的文件
entry:{ app: "./src/js/app.js", main: "./src/js/main.js" }
通常入口文件中可能是 import 或者 require 等模块导入命令。
output 顾名思义,Webpack打包后文件的具体配置 经常使用的属性有 4 个
path: ${__dirname }/dist
打包后文件所在路径
filename: "js/[name].js"
打包后文件的名字,这里有 4 种经常使用的写法
自定义
[name].js
表明的即是入口的文件名
[hash].js
这次打包后的hash值
[chunkhash]
该块打包后的hash值
publicPath: "http://cdn.com/"
上线时的公共路径,主要应用于线上
chunkFilename: 'js/[name].js'
按需加载模块时输出的文件名称
Loader 是 Webpack 中最振奋人心的东西了!
将一切浏览器不支持的语言,处理成 浏览器能够支持。 针对各个文件类型,都有各类的 Loader 等你去挖掘。
Loader 的工做方式 是从右向左执行,链式地按照顺序进行编译。 loader 链中的第一个返回值给下一个 loader,在最后一个 loader,返回所预期的结果。
loader 能够是同步或异步函数,也可以使用 options 对象去接受配置参数。
基础结构
module:{ rules:[ { test:/\.xxx$/,//以xxx结尾的文件 loader: "xxx-loader", exclude: {排除的路径}, include: {包含的路径}, options: {Loader配置} } ] }
能够很清楚的看到,Loader 利用 test 的正则 找到各个类型文件,而后使用 loader 进行处理,即可转换成浏览器支持的文件。
其中我知道的 loader 的写法有两种:
loaders:[ {loader:"style-loader"}, { loader: "css-loader?modules", options: { importLoaders: 1 } }, {loader: "less-loader"} ]
loader: "style-loader!css-loader?importLoaders=1!less-loader"
下面介绍三个 前端必备的 Loader 方式
style-loader
经过注入<style>
标签将 CSS 添加到 DOM
npm install style-loader --save-dev
css-loader
css-loader像import / require()同样解释@import和url()并解析它们。
npm install css-loader --save-dev
postcss-loader
补充 不兼容的css属性 的浏览器前缀
npm install post-loader --save-dev
less-loader
将Less 转换成 CSS
npm install less --save-dev npm install less-loader --save-dev
babel
主要用于将 es6 转换成 es2015
npm install --save-dev babel-core babel-loader babel-preset-es2015
file-loader
用于压缩文件
npm install --save-dev file-loader
url-loader
若是文件下于 规定限制,将会转换成 二进制编码
npm install --save-dev url-loader
另外 我想介绍一下 本身经常使用的 ejs-loader
npm install --save-dev ejs-loader
test:/\.ejs$/ , loader:"ejs-loader",
<div class="layer"> <div><%= name %></div> <% for(let i = 0; i < Array.length;++i) { %> <%= Array[i] %> <% } %> </div>
//入口文件 import tpl from "./layer.ejs"; document.body.innerHTML = tpl({ name:"Simon", arr:["Apple","Xiaomi"] });
运行 生成后的页面 ,便会发现 ejs 组件已经被加进去了, 想象一下,咱们在平时工做中是否能够把 一个轮播图,或者 排行榜 、评论 当成一个组件呢?
plugins
在平常工做中,咱们使用 Loader 处理不一样类型的文件,当有某种其余方面的需求时,好比 抽离 CSS 、生成多页面 HTML ,plugins 便派上了用场。
插件的使用,通常都要先 require 出来,而后在 plugins 属性中 进行初始化
const htmlWebpackPlugin = require("html-webpack-plugin"); ...... plugins: [ new htmlWebpackPlugin({/* options */}) ]
下面将介绍 一些工做中经常使用的插件
clean-webpack-plugin
主要用于 打包以前 先清空 打包目录下的文件,防止文件混乱。
npm install --save-dev clean-webpack-plugin
html-webpack-plugin
主要用于生成HTML,能够规定 模板HTML,也能够为 模板传入参数,压缩文件等
npm install --save-dev html-webpack-plugin
这个插件可谓是 前端必备的,它的配置有不少
new htmlWebpackPlugin({ //打包后的文件名 filename: "index.html", //模板 template: "index.html", //为true自动生成script标签添加到html中 //或者写 body/head 标签名 inject: false,//js的注入标签 //经过<%= htmlWebpackPlugin.options.title %>引用 title: "参数title", //经过<%= htmlWebpackPlugin.options.date %> 引用 date: new Date() //网站的图标 favicon: 'path/to/yourfile.ico' //生成这次打包的hash //若是文件名中有哈希,便表明有 合理的缓冲 hash: true, //排除的块 excludeChunks: [''], //选中的块 与入口文件相关 chunks: ['app','people'], //压缩 minify:{ removeComments: true,collapseWhitespace: true, minifyJS: true, minifyCSS: true,minifyURLs: true, } }),
那么问题来了,咱们在模板文件中 又该怎样使用参数呢? 直接按照 ejs 的语法写入 html 文件便可!
<!DOCTYPE html> <html lang="en"> <%= htmlWeb packPlugin.options.date %> </html>
生成后的模板文件
<!DOCTYPE html> <html lang="en"> Thu Dec 07 2017 10:01:58 GMT+0800 (中国标准时间) </html>
另外,若是想生成 多页面应用,只需 将上面的配置,多复制几遍便可。
new htmlWebpackPlugin({ filename: "index1.html", } new htmlWebpackPlugin({ filename: "index2.html", } new htmlWebpackPlugin({ filename: "index3.html", }
UglifyJsPlugin
主要用于压缩 Javascript 文件
npm i -D uglifyjs-webpack-plugin
webpack.ProvidePlugin
自动加载模块,全局使用变量,下面借助 官网的DEMO
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }) // in a module $('#item'); // <= 起做用 jQuery('#item'); // <= 起做用 // $ 自动被设置为 "jquery" 输出的内容
open-browser-webpack-plugin
打开服务器后 会自动打开浏览器端口,用起来 很方便
HotModuleReplacementPlugin
热更新插件
webpack
最基本的启动webpack命令
webpack -w
监控代码变化,实时进行打包更新
webpack -p
对打包后的文件进行压缩,利用线上发布
webpack -d
提供SourceMaps,方便调试代码
webpack --colors
输出结果带彩色,能够更详细的查看信息
webpack --profile
输出性能数据,能够看到每一步的耗时
不知道你如今时候有没有一个想法? webpack 打包后的文件就必定正确无误吗? 若是发生错误的话,该怎么办呢?
devtool 属性 便提供了生成 sourcemap 的功能,具体有下面这些选项。
source-map
此选项具备最完备的source map,但会减慢打包的速度;
cheap-module-source-map
生成一个不带列映射的map
eval-source-map
使用eval打包源文件模块,生成一个完整的source map。
cheap-module-eval-source-map
这是最快生成source map的方法,生成后的Source Map 会和打包后的 JavaScript 文件同行显示,但没有列映射,因此慎用
contentBase: "./dist",
本地服务器所加载的页面所在的目录
historyApiFallback: true,
再找不到文件的时候默认指向index.html
inline: true,
当源文件改变时会自动刷新页面
hot: true,
热加载开启
port:8080
设置默认监听端口
extensions: [".js", ".html", ".css", ".txt","less","ejs","json"],
自动扩展文件后缀名,意味着咱们require模块能够省略不写后缀名
alias: { Temp: path.resolve(__dirname, "src/templates/") }
模块别名定义,直接 require('AppStore') 便可,方便后续直接引用别名
经常使用于字符串拼接路径。
const path = require("path");
有两个 API
path.resolve()
将相对路径转换成绝对路径
const aPath = path.resolve("__dirname","js","main.js"); // aPath = 当前目录下的 js 文件夹的 main.js 文件的路径
path.join()
对路径进行拼接
const rPath = path.join("source","js","main.js"); // aPath = //source/js/main.js
上面咱们已经提过了 webpack -w
命令,它能够实时的监控 代码的改变,从而自动进行打包,可是 有个缺点 在于它不能及时的刷新界面。
在咱们 开启服务器后,是没法使用 此命令的,这个时候,若是你还想进行 自动打包,又想自动刷新界面,热更新 即是不二之选,另外 Webpack 只会热更新 发生改变的模块,不会从新加载整个页面,即可加快开发速度。
开启步骤:
devServer: { hot: true,//热加载开启 inline: true,//文件改变时会自动刷新页面 }
const webpack = require("webpack"); //Other property plugins: [ new webpack.HotModuleReplacementPlugin() ]
另外,只有修改 依赖的项目,才会进行实时更新。
如今是一个 Web 技术蓬发的时代,必定要把握住时代潮流。
在写这篇文章前,我已经花了一成天的时间,把工做所须要 几乎全部的 Loader , plugins 收集了一遍,专门写了个源文件。但由于个人源文件太大 必须可显示,可隐藏,否则影响阅读 ,可开源中国的 Markdown 不支持自定义样式 ,因此我贴在了个人博客,但愿它能对你有帮助。
另外,再送你个福利,若是你是我的博客爱好者,我最近新开发了一款美观开源的主题,等待你的使用。