webpack初步了解
2018-03-12 16:31
417 查看
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 代码,压缩合并图片等。
模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。
代码校验:在代码被提交到仓库前需要校验代码是否符合规范,以及单元测试是否通过。
常用的构建工具
gruntgulp
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
相关文章推荐
- webpack初步了解
- webpack初步了解
- webpack初步了解
- webpack初步了解
- webpack初步了解
- webpack初步了解
- 配置Webpack-dev-server+初步了解react中元素、组件、事件、props传递
- webpack的初步了解
- WebPack初步入门
- android WebView 初步了解
- 学习笔记 一步步了解webpack
- Servlet的初步了解 --- JavaWeb
- 快速了解 webpack 前端打包
- vue学习 - webpack (初步)手动配置方法
- webpack+react.js搭建初步
- ES6+React+Webpack初步构建项目流程
- 一步一步的了解webpack4的splitChunk插件(小结)
- vue.js基本使用 利用webpack"热"运行vuejs+html初步和关键步骤 <二>
- Webpack 3 —— 了解
- webpack和gulp"勾结"初步