使用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 相关文章推荐
让图片旋转任意角度及JQuery插件使用介绍
Mar 20 Javascript
微信中一些常用的js方法汇总
Mar 12 Javascript
jQuery $.each遍历对象、数组用法实例
Apr 16 Javascript
探寻JavaScript中this指针指向
Apr 23 Javascript
Bootstrap中的Panel和Table全面解析
Jun 13 Javascript
JavaScript 实现 Tab 点击切换实例代码
Mar 25 Javascript
JavaScript使用math.js进行精确计算操作示例
Jun 19 Javascript
微信小程序实现循环动画效果
Jul 16 Javascript
Vue实现移动端页面切换效果【推荐】
Nov 13 Javascript
vue权限问题的完美解决方案
May 08 Javascript
生产制造追溯系统之再说条码打印
Jun 03 Javascript
vue axios post发送复杂对象问题
Jun 04 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
php rsa加密解密使用详解
2015/01/14 PHP
php实现计算百度地图坐标之间距离的方法
2016/05/05 PHP
php解析mht文件转换成html的实例
2017/03/13 PHP
jQuery toggle()设置CSS样式
2009/11/05 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
jquery动态加载js三种方法实例
2013/08/03 Javascript
原生JS实现加入收藏夹的代码
2013/10/24 Javascript
js比较日期大小的方法
2015/05/12 Javascript
初识angular框架后的所思所想
2016/02/19 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
JavaScript基本类型值-Undefined、Null、Boolean
2017/02/23 Javascript
jQuery插件FusionCharts绘制的2D帕累托图效果示例【附demo源码】
2017/03/28 jQuery
vue如何获取点击事件源的方法
2017/08/10 Javascript
浅谈node模块与npm包管理工具
2018/01/03 Javascript
基于vue 添加axios组件,解决post传参数为null的问题
2018/03/05 Javascript
JavaScript捕捉事件和阻止冒泡事件实例分析
2018/08/03 Javascript
JS 验证码功能的三种实现方式
2018/11/26 Javascript
vue router返回到指定的路由的场景分析
2020/11/10 Javascript
[02:11]2016国际邀请赛中国区预选赛最美TA采访现场玩家
2016/06/28 DOTA
python编程培训 python培训靠谱吗
2018/01/17 Python
python爬取微信公众号文章
2018/08/31 Python
python 实现倒排索引的方法
2018/12/25 Python
python logging模块的使用总结
2019/07/09 Python
pandas 选取行和列数据的方法详解
2019/08/08 Python
Python操作多维数组输出和矩阵运算示例
2019/11/28 Python
Python函数参数类型及排序原理总结
2019/12/19 Python
利用Pytorch实现简单的线性回归算法
2020/01/15 Python
使用Python脚本从文件读取数据代码实例
2020/01/19 Python
python线程池如何使用
2020/05/28 Python
python反扒机制的5种解决方法
2021/02/06 Python
html5中canvas图表实现柱状图的示例
2017/11/13 HTML / CSS
德国电子商城:ComputerUniverse
2017/04/21 全球购物
韩国现代百货官网:Hmall
2018/03/21 全球购物
世界上最大的艺术和工艺用品商店:MisterArt.com
2018/07/13 全球购物
Python anaconda安装库命令详解
2021/10/16 Python
介绍一下28个JS常用数组方法
2022/05/06 Javascript