webpack使用

时间:2022-09-30 11:23:55

Webpack是一个现代js应用的模块打包机。如果一个文件依赖另一个文件,webpack认为这就存在一个依赖关系。不管另一个文件是什么内容,image,css或js都被当作一个模块。Webpack从entry points开始构建依赖关系图,将应用所需要的所有模块处理成浏览器可识别的格式,再打包成一批(个)文件,将来发送给浏览器。
chunk:多个模块打包之后的代码集合。

使用步骤:

1.全局安装webpack

  npm install -g webpack

  如果没有package.json,使用CLI创建:npm init

2.项目根目录安装webpack

  npm install --save-dev webpack

3.配置webpack.config.js文件,运行webpack命令时不用再输入参数

4.运行webpack

在项目根目录通过CLI调用:$webpack   #必须全局安装,否则需要指定webpack.bat的文件路径
  webpack默认只会在当前shell工作目录找webpack.config配置文件;如果配置文件不在shell当前工作目录,可以通过--config ./file/pathOfConfig 进行传参数。如果没有配置文件,则需要输入webpack <entry> <output>.
  webpack内部自定义了一些参数的映射,运行webpack时可以传入,如--debug映射为debug:true;-p映射为--optimize-minimize --optimize-occurrence-order.
  单双连字符的使用没有特殊规定:Two hyphen-minus characters ( -- ) are used on some programs to specify "long options" where more descriptive option names are used.单连字符取代驼峰命名,用于连接单词或指定很短的参数选项(通常只有一个字母)。

或在Node中调用

var webpack = require('webpack');  //只需要本地安装即可
var config2 = require('./webpack.config');
var compiler = webpack(config2);

webpack的配置文件webpack.config.js

如果该文件存在,只需要执行CLI命令:$webpack,webpack就会自动读取配置,并输出打包的文件。配置文件是以js文件的形式代替命令行形式参数,是符合commonjs规范的node模块,里面可以有function和require(),只要最后以对象形式输出配置即可。

具体配置信息如下:

devtoolsource-map.生成何种类型的source map,方便打包后的调试。

entry webpack从哪里开始构建整个依赖关系。动态的模块不能是entry point。一般一个HTML页面一个entry point。如果有多个entry point,可以采用对象形式定义。不支持通配符配置。如果确实有需要,用如下sinppet,然后将entries传入webpack.config中,或利用node-glob模块读取文件名。

var glob = require("glob");  // Match files using the patterns the shell uses

entry: glob.sync("./src/scripts/*.js")

output打包后输出的路径(path)和输出的文件名(filename)。可以有多个entry point,但只能有一个output。

如果是多entry,filename需要使用替换保证每个输出文件的名字唯一:

  [name] is replaced by the name of the chunk.

  [hash] is replaced by the hash of the compilation.(compilation对象的hash值,和webpack的compiler环境相关,同一次编译时的值一样)

  [chunkhash] is replaced by the hash of the chunk.(具体模块的hash值,和整个文件内容相关。内容不变,chunkhash值不变)

loaderswebpack将每个资源文件当作一个模块,但是webpack只能处理js。通过loaders将其他格式的资源文件转换成模块后(比如将JSX语言转换成js、将coffeescript转换成js)加入依赖关系中,最后打包输出。需要单独安装包并且在webpack.config.js下的modules关键字下进行配置loaders后才能使用。 loders下的字段:

  test:确定哪些文件将被加载器处理;

  user:使用哪个加载器,”-loader”后缀不能省略;

  include/exclude:必须处理或屏蔽不需要处理的文件(文件夹)(可选);

  options:当前loader需要的特殊配置(可选),如babel-loader的.babelrc配置文件里的信息。webpack2.5之前为query

plugins扩展Webpack功能,会在整个构建过程中生效,执行相关的任务。需要通过require()引入并将插件实例添加到plugins数组中。

resovle通过别名、扩展名、根路径或备用目录等属性决定webpack如何更快找到import/require()的模块。

  resolve.alias:用别的路径或模块替代。把requirejs项目改为webpack项目时可以利用此属性。

  resolve.extensions:通过扩展名组成的数组解析require()的模块文件。比如加载一个coffeeScript文件,需要增加’.coffee’扩展名。若修改后必须增加空字符串为第一个元素。

常用命令:webpack  –watch改动代码后自动打包

自动刷新页面显示修改后的效果

使用webpack-dev-server模块构建本地服务器:

  npm install --save-dev webpack-dev-server

安装完毕之后运行$webpack-dev-server --open

如果报命令不识别的错误,可在package.json的script字段添加("start": "webpack-dev-server --progress  --hot --inline --content-base ./dist"),然后运行$npm start命令;

或再全局安装一次。

压缩bundle.js文件的大小

//会加载整个lodash,所以体积更大
import { concat, sortBy, map, sample } from 'lodash';
//Use relative file paths,只加载需要的函数模块,体积更小
//例如import { Button } from 'antd';使用babel-plugin-import插件==》var _button = require('antd/lib/button');
import concat from 'lodash/concat';
import sortBy from 'lodash/sortBy';
import map from 'lodash/map';
import sample from 'lodash/sample';

生产环境中要删除sourcemap

使用 webpack –p命令构建bundle.js

通过命令webpack --profile --json >> stats.json生成构建过程的文件,在 https://webpack.github.io/analyse上分析哪个模块占用的空间大。或者使用webpack-bundle-analyzer插件,用视图的形式分析bundle.js中的每个模块。

var debug = process.env.NODE_ENV !== 'production'; //是否是开发模式,生产模式时需要去除sourcemap
const webpack = require('webpack'); //访问内置插件
const path = require('path');
var htmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm const config = {
devtool: debug ? 'cheap-eval-source-map' : undefined, //开发模式时生成何种类型的源代码映射文件,方便调试打包后的代码
entry: { //webpack打包的切入点,一般一个页面的业务代码定义一个entry point,key为输出chunk的name
home: ['./footer.js', './home.js'], //若为[string],则将多个相互独立的文件及其依赖打包成一个chunk
about: './about.js',
contact: './contact.js',
vendor: ['jquery', 'lodash', 'vue'] // 使用commonschunkplugin抽离的公共模块
},
output: { //输出配置项
path: path.resolve(__dirname, 'dist'), //打包后输出的路径
filename: '[name].[chunkhash:8].js', //打包后输出的文件名,多个entry需要替换
chunkFilename: '[id].js', //name of non-entry chunk files。浏览器按需加载的chunk
publicPath: 'http://cdnOfCompany.com/' // 供webpack及插件在生产模式下更新内嵌到css、html文件里的cdn路径
},
resolve: {
extensions: ['', '.js', '.vue'],
fallback: [path.join(__dirname, '../node_modules')],
alias: {
'@': resolve('src'), //别名,js中import时使用,在src和@import中需要加 ~
'moment': path.join(__dirname, '../node_modules/moment/min/moment-with-locales.min.js'), // 为模块配置别名
}
},
externals: {
'jquery': 'jQuery' // 希望通过script标签引进的依赖,可以require/import,但不打包进bundle。必须先加载,webpack会以module的形式对其引用。
},
module: { // webpack2.0的字段名做了些修改
rules: [//每条rule定义对应的module如何生成,是loaders的alias
{
test: /\.(js|jsx)$/, //一个匹配loaders所处理的文件的拓展名的正则表达式
exclude: /(node_modules|bower_components)/,
use: [   //使用到的loader及其配置
{
loader: 'babel-loader', //使用的加载器名称,-loader后缀不能省略;也可通过?query设置参数
options: { //为当前loader设置的参数,对于babel可以提取出单独放在.babelrc文件中;
presets: ['react', 'es2015'],
plugins: [require('react-html-attrs')]
}
}
]
}, {
test: /\.css$/,
exclude: /(node_modules)/, //手动添加必须处理(include)或屏蔽不需要处理的文件(文件夹)
use: [//使用多个loader处理同一源文件,从右往左顺序处理
//css-loader将css文件当作一个模块引入当前模块中,类名相同样式也不会冲突;style-loader将当前模块中的样式引入页面的style元素中
{
loader: 'style-loader'
}, {
loader: 'css-loader',
options: {
importLoaders: 1
}
}, {
loader: 'less-loader',
options: {
noIeCompat: true
}
}
]
}, {
// 解决图片的路径在发布前后不一致的问题(资源打包前在/src/assert和/static中,打包后全部归并到/dist/static目录下)
//vue-cli中:assert中的资源要经过webpack处理,只能通过相对路径(视为模块依赖)访问;/static中的资源不用经过webpack处理,通过绝对路径访问
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, // 小于8kb的直接转为base64
loader: 'url-loader',
options: {
limit: 8192,
name: utils.assetsPath('img/[name].[hash:7].[ext]') // 被加载器处理后重写的url路径,打包之后图片也会被复制到dist的该路径中
}
}
]
},
plugins: debug ? [] : [//添加插件实例
//依据模板,生成最终的html文件。该文件中会生成标签自动引用了打包后的js/css文件,不用手动一个一个修改url。
new htmlWebpackPlugin({ // 一个单页应用配置一个该实例,多个页面配置多个
filename: 'index.html', //输出文件的名字
template: './src/index.tpl', //使用的模板文件
title: 'this is home page', //传入模版的参数,在模版中可以通过<%=htmlWebpackPlugin.options.title%>获取该值;也可以传递其他自定义的属性供模板使用,如css等静态资源,不会被当做依赖被打包。
favicon: 'path/to/yourfile.ico', //生成的 html 标签中会包含这样一个 link 标签指向favicon
inject: 'body', //插入script的位置
chunks: ['vendor', entry], //不设置时默认包含entry中所有的chunks(包括CommonsChunkPlugin插件生成的chunk)
excludeChunks: ['contact', 'other chunk']//排除引入的chunk
}),
new webpack.optimize.DedupePlugin(),
new webpack.NoErrorsPlugin(), //构建过程中发生error时跳过错误继续生成
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({ // webpack定义的全局常量,编译后会替换成value对应的文本,减少手动一个修改 去除对warning和一些提示信息的代码
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
// https://github.com/LiPinghai/UglifyJSDocCN/blob/master/README.md
new webpack.optimize.UglifyJsPlugin({ //简化压缩代码,去除console,warning等语句
sourcemap: false,
compress: {
screw_ie8: true,
warnings: false,
drop_debugger: true, // 去除debugger语句
pure_funcs: ['console.log'], // 发布时不被打包的函数
dead_code: true // 去除不被执行的代码
},
mangle: {
screw_ie8: true
},
output: {
comments: false,
screw_ie8: true
}
}),
// http://webpack.github.io/docs/list-of-plugins.html
// https://*.com/questions/39548175/can-someone-explain-webpacks-commonschunkplugin
new webpack.optimize.CommonsChunkPlugin({ //把所有入口节点的公共代码提取出来,生成一个chunk(name为common.js)进行复用
names: ['vendor', 'manifest'], // 需要抽离的公共模块的名字。配置manifest,其他代码改变但vendor不变化时common.js不变,但manifest的hash值改变(因为含有webpack runtime代码)
filename: 'commons.js', // 最后生成公共chunk的文件名,优先于output里的filename配置。不建议固定文件名,如果更新了不方便用户重新下载。
minChunks: Infinity // with more entries, this ensures that no other module goes into the vendor chunk
}),
new webpack.DllReferencePlugin({ // 引用dll包中的模块,在dll包中无法找到时才打包进当前bundle
context: __dirname,
manifest: require('./manifest.json')
}),
// 复制/static目录中的资源到 dist/static下对应的目录中
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory, // dist/static下
ignore: []
}
])
],
watch: true, //监听源文件的修改,之后recompile,但不刷新页面。为了提高性能,需要将safe write关闭,用save file触发。
watchOptions: {
aggregateTimeout: 300, //从修改文件开始到rebuilding的延迟时间,将多个改变积累到一起
poll: 1000, //Check for changes every second
ignored: /node_modules///排除监听的目录
},
devServer: { //构建本地服务器实时提供服务并刷新,编译后的文件保存在内存中,所以比较快。
contentBase: './', //本地服务器所提供服务的内容来源
port: 8080, //监听端口,和编辑器的端口不一样
colors: true, //终端中输出结果为彩色
historyApiFallback: true, //所有的跳转将指向index.html
inline: true //会输出错误
}
};
module.exports = config;

code-spitting

/**每个打包后的bundle都有一个webpack启动函数,负责在客户端启动js;使用commonchunkplugin后runtime函数在最后一个chunk中**/ (function(modules) { // webpackBootstrap 

原因:webpack全部打包进一个文件,只要一修改代码,hash就会改变,客户端只能重新下载无法利用缓存。另外有些模块特定的用户不一定用到,首次访问时全部加载会影响首屏速度。

方法:

1. 分离业务逻辑,使用CommonsChunkPlugin打包第三方类库,注意需要在业务逻辑模块之前下载公共模块,因为webpackBootstrap函数会在公共模块中。

<script src="common.js" charset="utf-8"></script>    // webpackBootstrap
<script src="app.js" charset="utf-8"></script> // webpackJsonp

2. 动态加载指定模块

import()语法

// other logic
import('./sideAd').then(_ => doSomething()).catch(error => 'An error occurred while loading the component');
require.ensure([dependency],function(require){var footAd = require('./footAd') })
// webpack在静态打包时,会将sideAd模块当做单独的chunk打包,将footAd及其依赖单独打包(被webpackJsonp函数包裹),这样当前模块文件体积就会减小

webpack将import('...')转变成``__webpack_require__.e/* import() */(n).then()``*或者``__webpack_require__.e/* require.ensure */(0).then((function (require) {__webpack_require__(n)}))``的形式,在浏览器中webpackbootstrap会*通过__webpack_require__.e(JSONP方法)动态加载chunkId为n的模块。*
require():在webpack项目中只能静态打包到bundle中。依赖都被加载且都被执行后才执行回调函数。
require.ensure():单独打包,动态加载。依赖被下载后不会被执行,只有在回调函数**再次**使用require(module)后,这个模块才会被执行。

3. 使用DllPlugin和DllReferencePlugin

将经常使用的库文件打包到dll包中,它本身不能运行,是用来给业务代码引用的。分离了第三方库,打包速度更快,而且不受业务模块的chunkhash影响。使用步骤:
a. 使用webpack.DllPlugin插件打包第三方库
b. 在主配置文件中使用webpack.DllReferencePlugin插件引用dll包

4. 对于单页应用,可以使用bundle-loader异步加载各路由对应的组件(懒加载),尽快显示首屏。
5. 在vue-router中,使用``const Foo = () => import('./Foo.vue')``懒加载。

    routes: [
{
path: '/',
name: 'Hello',
component: () => import('../module/HelloWorld')
},
{
path: '/check',
name: 'check',
component: r => require(['@/pages/spa/module/CheckBox'], r)
}
]

webpack使用的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. webpack之傻瓜式教程

    接触webpack也有挺长一段时间了,公司的项目也是一直用着webpack在打包处理,但前几天在教新人的情况下,遇到了一个问题,那就是:尽管网上的webpack教程满天飞,但是却很难找到一个能让新人快 ...

  3. 细说前端自动化打包工具--webpack

    背景 记得2004年的时候,互联网开发就是做网页,那时也没有前端和后端的区分,有时一个网站就是一些纯静态的html,通过链接组织在一起.用过Dreamweaver的都知道,做网页就像用word编辑文档 ...

  4. Webstorm&plus;Webpack&plus;echarts构建个性化定制的数据可视化图表&amp&semi;&amp&semi;两个echarts详细教程(柱状图,南丁格尔图)

    Webstorm+Webpack+echarts   ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...

  5. 使用webstorm&plus;webpack构建简单入门级&OpenCurlyDoubleQuote;HelloWorld”的应用&amp&semi;&amp&semi;引用jquery来实现alert

    使用webstorm+webpack构建简单入门级"HelloWorld"的应用&&构建使用jquery来实现 1.首先你自己把webstorm安装完成. 请参考这 ...

  6. webpack入门教程之Hello webpack&lpar;一&rpar;

    webpack入门教程系列为官网Tutorials的个人译文,旨在给予想要学习webpack的小伙伴一个另外的途径.如有不当之处,请大家指出. 看完入门教程系列后,你将会学习到如下内容: 1.如何安装 ...

  7. webpack的使用

    1.webpack是什么? 打包前端项目的工具(为项目提高逼格的东西). 2.webpack的基本命令 webpack#最基本的启动webpack命令 webpack-w #提供watch方法,实时进 ...

  8. Webpack 配置摘要

    open-browser-webpack-plugin 自动打开浏览器 html-webpack-plugin 通过 JS 生成 HTML webpack.optimize.UglifyJsPlugi ...

  9. Vue &plus; Webpack &plus; Vue-loader 系列教程(2)相关配置篇

    原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ 使用预处理器 在 Webpack 中,所有的预处理器需要和一个相应的加载器一同使用.vue- ...

  10. Vue &plus; Webpack &plus; Vue-loader 系列教程(1)功能介绍篇

    原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue-loader 是一个加载器,能把如下格式的 Vue ...

随机推荐

  1. 错误信息:System&period;Resources&period;MissingManifestResourceException&colon; 未能找到任何适合于指定的区域或非特定区域性的资源。请确保在编译时已将&OpenCurlyDoubleQuote;&ast;&ast;&ast;&ast;&period;&ast;&ast;&ast;&ast;&period;Resource&period;resources”正确嵌入或链接到程序集&quot&semi;&ast;&ast;&ast;&ast;&quot&semi;,或者确保所有需要的附属程序集都可加载并已进行了完全签名

    在网上搜索了N久都没看到几篇解决的文章,最后在不懈的努力下终于解决了,所以决定写下解决方法方便以后遇到同样问题的朋友: 其实这个错误的主要问题就是没有找到需要的资源文件(该文件为Resources.r ...

  2. git使用具体介绍

    1. Git概念  1.1. Git库中由三部分组成         Git 仓库就是那个.git 文件夹,当中存放的是我们所提交的文档索引内容,Git 可基于文档索引内容对其所管理的文档进行内容追踪 ...

  3. grunt serve Fatal error&colon; Port 35729 is already in use by another process&period;

    y@y:~$ lsof | grunt y 0t0 TCP *: (LISTEN) Optimizin y 0t0 TCP *: (LISTEN) v8:Sweepe y 0t0 TCP *: (LI ...

  4. 关于jQuery的ajax的源码的dataType解读

    $.ajax其实底层还是用的XMLHttpRequest,对于加载数据的格式datatype有:xml.text.html.json.jsonp.script. 其中xml.text不需要处理,直接使 ...

  5. hadoop MapReduce - 从作业、任务(task)、管理员角度调优

    Hadoop为用户作业提供了多种可配置的参数,以允许用户根据作业特点调整这些参数值使作业运行效率达到最优. 一 应用程序编写规范 1.设置Combiner         对于一大批MapReduce ...

  6. 第一次安装jshint,jshint新手使用记录

    刚刚出来工作的渣渣,第一次进入这样比较正规的公司,各个开发流程都比较严格,代码也是要经过jshint的检测才能上传到svn才能成功打包项目.所以我这种技术都半桶水的职场开发小白,也是第一次用jshin ...

  7. android studio运行的时候出现Unable to obtain debug bridge错误的解决办法

    先贴上我百度的: 首先利用win+R,输入cmd,并且输入命令好来到:cd D:\Android\sdk\platform-tools\(这个是我的adb.exe目录,你的可以自行搜索)然后输入:ad ...

  8. webrtc如何进行错误恢复

    视频的压缩方法:(三种帧) 为了视频尽可能的保持高效,视频数据通过不同的编码进行压缩.以帧为单位进行压缩,按照压缩中的不同作用可分类为:内帧(Intra-frames,I帧),预测帧(Predicti ...

  9. android app主程序启动前加载图片

    android app加载启动图片需要新创建一个activity,在主activity先加载图片activity,展示过程结束后,显示主activity.具体流程如下: 一.创建图片activity的 ...

  10. ORACLE11g下如何利用SQL DEVELOPER连接上数据库

    最近在学习数据库的相关内容,在sqlplus敲了几天命令行窗口后,想尝试一下用sql developer 连接上数据库但一直没有实现.在网上查询了相关资料后现在终于弄好了,就来写下此篇博文与大家分享! ...