使用webpack构建应用的方法步骤


Posted in Javascript onMarch 04, 2019

如何使用webpack

npm init -y
npm install webapck webpack-cli --save-dev
touch webpack.config.js

在webpack.config.js中下面添加内容

const path = require('path');

module.exports = {
 entry: './src/index.js',
 output: {
  filename: 'main.js',
  path: path.resolve(__dirname, 'dist')
 }
};
  • entry:工程资源的入口,可以是单个文件,也可以是多个文件,通过每一个资源入口,webpack会一次去寻找它的依赖进行模块打包。我们可以把entry理解为整个依赖树的根,每个入口都将对应一个最终生成的打包结果。
  • output:这是一个配置对象,通过它我们可以对最终打包的产物进行配置,这里配置了两个属性,:
    • path:打包资源放置的路劲,必须为绝对路径。
    • filename:打包结果的文件名。

定义好配置文件后,用npx webpack或者./node_modules/.bin/webpack执行

使用loader

项目中需要引入一个css文件,如果直接用webpack去执行就会报错,需要再webpack中加入loader机制

module.exports = {
  ...
  module: {
    rules: [
      {
        // 用正则去匹配 .css 结尾的文件,然后需要使用 loader 进行转换
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
}

编译之前还需要安装style-loader和css-loader

npm install --save-dev style-loader css-laoder

注意:

use属性的值是一个使用loader名称组成的数组,loader执行的顺序是从后往前的,由于loader执行有顺序,故不能写成这样

use: ['css-loader', 'style-loader']

每个loader都可以通过URL queryString的方式传入参数,比如'css-loader?url'

style-loader的原理:是将css的内容使用javascript的字符串存储起来,在网页执行javascript时通过DOM操作,动态地向HTML head标签里插入HTML style标签。

配置loader的方式也可以用Object来实现

use: ['style-loader', {
  loader: 'css-loader',
  options: {
    url: true
  }
}]

使用plugin

loader的作用是被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务,插件的范围包括,从打包优化和压缩,一直到重新定义环节中的变量。

如果想要使用一个插件,我们只需要require()它,然后把它添加到plugins数组中。我们可以在一个配置文件中因为不同的目的多次使用用一个插件,因此我们可以使用new操作符来创建它的实列。

上面使用loader把css加载到js中去,现在使用extract-text-webpack-plugin插件把bundle.js文件里的css提取到单独的文件中

// 提取 css 的插件
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module: {
  rules: [
    {
      // 用正则去匹配 .css 结尾的文件,然后需要使用 loader 进行转换
      test: /\.css$/,
      loaders: ExtractTextPlugin.extract({
        //转换 .css需要使用的 loader
        use: ['css-loader']
      })
    }
  ]
},
plugins: [
  //从 js 文件中提取出来的 .css 文件名称
  new ExtractTextPlugin({
    filename: 'main.css'
  })
]

编译之前需要安装extract-text-webpack-plugin

npm install --save-dev extract-text-webpack-plugin

执行webpack时报错需要这样安装

npm install extract-text-webpack-plugin@next

DevServer

官方网站

安装

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

然后进行简单的配置

devServer:{
  port: 3000,
  publicPath: "/dist"
}

然后用./node_modules/.bin/webpack-dev-server执行

资源压缩

npm i uglifyJSPlugin-webpack-plugin --save-dev

配置文件

const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
plugins: [
  new UglifyJSPlugin({
    //默认是 false 需要手动开启
    parallel: true
  })
]

或者

optimization: {
  minimizer: [new UglifyJsPlugin()],
},

按需加载

在代码层面,webpack支持两种方式进行异步模块加载,一种是CommonJS形式的require.ensure,一种是ES6 Module形式的异步import()

异步加载的脚本不允许使用document.write,所以将module.js的代码改成console.log

export const log = function(){
  console.log('module.js loaded.')
}

编辑app.js,将module.js以异步的形式加载进来

import('./module.js').then(module =>{
  module.log()
}).catch(error => "An error occurred while loading the module")
document.write('app.js loaded.')

修改配置

module.exports = {
  mode: "production",
  entry: './app.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: "./dist"
  },
}

这里我们在output中添加了一个配置项publicPath,它是webpack中一个很重要有很容易引起迷惑的配置,当我们的工程中有按需加载以及图片和文件等外部资源时,就需要它来配置这些资源的路径,否则页面上就会报404,这里我们将publicPath配置为相对于html的路径,使按需加载的资源生产在dist目录下,并且能正确地引用到它。

重新打包之后你会发现打包结果中多出一个1.mian.js,这里面就是将来会被异步加载进来的内容。刷新页面并查看chrome的network标签,可以看到页面会请求1.main.js。它并不来源于index.html中的引用,而是通过main.js在页面插入了script标签来将其引入的。

使用webpack的构建特性

从2.0.0版本开始,webpack开始加入了更多的可以优化构建过程的特性。

tree-shaking

在关于模块的那一篇文章中我们提到过,ES6 Module的模块依赖解析是在代码静态分析过程中进行的。换句话说,它可以在代码的编译过程中得到依赖树,而非运行时。利用这一点webpack提供tree-shaking功能,它可以帮助我们检测工程中哪些模块有从未被引用到的代码,这些代码不可能被执行到,因此也称为“死代码”。通过tree-shaking,webpack可以在打包过程中去掉这些死代码来减小最终的资源体积。

开启tree-shaking特性很简单,只要保证模块遵循ES6 Module的形式定义即可,这意味着之前所有我们的例子其实都是默认已经开启了的。但是要注意如果在配置中使用了babel-preset-es2015或者babel-preset-env,则需要将其模块依赖解析的特性关掉,如:

presets: [
  [env, {module: false}]
]

这里我们测试一下tree-shaking的功能,编辑module.js:

// module.js 
export const log = function() { 
  console.log('module.js loaded.'); 
} 

export const unusedFunc = function() { 
  console.log('not used'); 
}

打开页面查看1.main.js的内容,应该可以发现unusedFunc的代码是不存在的,因为它没有被别的模块使用,属于死代码,在tree-shaking的过程中被优化掉了。

tree-shaking最终的效果依赖于实际工程的代码本身,在我对于实际工程的测试中,一般可以将最终的体积减小3%~5%。总体来看,我认为如果要使tree-shaking发挥真正的效果还要等几年的时间,因为现在大多数的npm模块还是在使用CommonJS,因此享受不了这个特性带来的优势。

scope-hoisting

scope-hoisting(作用域提升)是由webpack3提供的特性。在大型的工程中模块引用的层级往往较深,这会产生比较长的引用链。scope-hoisting可以将这种纵深的引用链拍平,使得模块本身和其引用的其它模块作用域处于同级。这样的话可以去掉一部分 webpack的附加代码,减小资源体积,同时可以提升代码的执行效率。

目前如果要开启scope-hoisting,需要引入它的一个内部插件:

module.exports = { 
  plugins: [ 
    new webpack.optimize.ModuleConcatenationPlugin() 
  ] 
}

scope-hoisting生效后会在bundle.js中看到类似下面的内容,你会发现log 的定义和调用是在同一个作用域下了:

// CONCATENATED MODULE: ./module.js 
const log = function() { 
  console.log('module.js loaded.'); 
} 

// CONCATENATED MODULE: ./app.js 
log();

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 判断 object 的特定类转载
Feb 01 Javascript
需要做特殊处理的DOM元素属性的访问
Nov 05 Javascript
JS实现随机化快速排序的实例代码
Aug 01 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
Nov 23 Javascript
使用AngularJS编写较为优美的JavaScript代码指南
Jun 19 Javascript
js实现跨域的4种实用方法原理分析
Oct 29 Javascript
解决vue+webpack打包路径的问题
Mar 06 Javascript
手写简单的jQuery雪花飘落效果实例
Apr 22 jQuery
脚手架vue-cli工程webpack的基本用法详解
Sep 29 Javascript
详解Vue路由自动注入实践
Apr 17 Javascript
Vue强制组件重新渲染的方法讨论
Feb 03 Javascript
js闭包的9个使用场景
Dec 29 Javascript
详解element-ui中form验证杂记
Mar 04 #Javascript
JS使用数组实现的队列功能示例
Mar 04 #Javascript
JS使用栈判断给定字符串是否是回文算法示例
Mar 04 #Javascript
微信小程序textarea层级过高(盖住其他元素)问题的解决办法
Mar 04 #Javascript
一步快速解决微信小程序中textarea层级太高遮挡其他组件
Mar 04 #Javascript
使用ESLint禁止项目导入特定模块的方法步骤
Mar 04 #Javascript
微信小程序textarea层级过高的解决方法
Mar 04 #Javascript
You might like
Docker配置PHP开发环境教程
2016/12/21 PHP
thinkPHP5.0框架开发规范简介
2017/03/25 PHP
popdiv
2006/07/14 Javascript
Ext javascript建立超链接,进行事件处理的实现方法
2009/03/22 Javascript
JavaScript Cookie的读取和写入函数
2009/12/08 Javascript
jQuery 动态酷效果实现总结
2009/12/27 Javascript
jquery 插件实现图片延迟加载效果代码
2010/02/06 Javascript
CutePsWheel javascript libary 控制输入文本框为可使用滚轮控制的js库
2010/02/07 Javascript
JavaScript 继承机制的实现(待续)
2010/05/18 Javascript
jquery 插件学习(一)
2012/08/06 Javascript
Jquery 复选框取值兼容FF和IE8(测试有效)
2013/10/29 Javascript
js简单的表格添加行和删除行操作示例
2014/03/31 Javascript
jQuery的promise与deferred对象在异步回调中的作用
2016/05/03 Javascript
AngularJS基础 ng-cloak 指令简单示例
2016/08/01 Javascript
BootStrap Datetimepicker 汉化的实现代码
2017/02/10 Javascript
jquery在启动页面时,自动加载数据的实例
2018/01/22 jQuery
vue脚手架搭建项目的兼容性配置详解
2018/07/17 Javascript
解决antd Form 表单校验方法无响应的问题
2020/10/27 Javascript
[01:09:23]KG vs TNC 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python中方法链的使用方法
2016/02/23 Python
python学习之编写查询ip程序
2016/02/27 Python
Python安装图文教程 Pycharm安装教程
2018/03/27 Python
Python实现字符串的逆序 C++字符串逆序算法
2020/05/28 Python
用TensorFlow实现戴明回归算法的示例
2018/05/02 Python
python requests.post带head和body的实例
2019/01/02 Python
python 发送和接收ActiveMQ消息的实例
2019/01/30 Python
使用python itchat包爬取微信好友头像形成矩形头像集的方法
2019/02/21 Python
如何基于pythonnet调用halcon脚本
2020/01/20 Python
Python数组拼接np.concatenate实现过程
2020/04/18 Python
python用opencv完成图像分割并进行目标物的提取
2020/05/25 Python
python collections模块的使用
2020/10/16 Python
Html5无刷新修改browser Url的方法
2014/01/15 HTML / CSS
h5页面唤起app如果没安装就跳转下载(iOS和Android)
2020/06/03 HTML / CSS
师范生自荐信模板
2014/05/28 职场文书
如何在python中实现ECDSA你知道吗
2021/11/23 Python
pytorch中的torch.nn.Conv2d()函数图文详解
2022/02/28 Python