详解Web使用webpack构建前端项目


Posted in Javascript onSeptember 23, 2017

好久没写技术博客了, 原因在于最近在学习前端方面的技术, 熟悉我的同学都知道, 之前我有使用Vue搭建了一个个人简历, 体验了一把最新的前端技术, 但之前我们使用的是vue-cli脚手架工具, 对于如何自己实现前端构建工具, 当下最为流行的就是webpack和gulp了, 之前一篇我们讲了gulp, 这一篇我们来好好讨论webpack.

详解Web使用webpack构建前端项目

说起webpack, 想必做前端的同学肯定不会陌生, 其实之前我们使用gulp构建的时候, 也使用了webpack的打包技术, 其实gulp和webpack并不是相互替代的关系, 而是相辅相成, 今天我们就来好好看看webpack的神奇之处吧.

我们学习一样新技术, 首先肯定是从他的官方文档入手, 当然我们要学习也是学最新版的.webpack的官方教程写的非常好, 一步一步讲的很到位, 各位同学可以直接阅读官方文档, 比起博客中的二手, 三手以及四手的资料, 官方文档肯定是你更好的选择.

这篇文章, 不是教你什么看这一篇就够了之类的对于官方文档拷贝的水文, 而是能让你快速上手并且觉得所谓的webpack其实也就这么一回事, webpack你只要记住一个中心思想, 就和上面的图示一样, 将所有错综复杂的文件逻辑打包压缩成几个静态资源, 不多说了, 我们还是看代码来的实际.

webpack.config.js

对于一些抛弃jquery迎接react和vue的前端开发者来说, webpack虽然可能自己没有写过, 但看总是看过的吧, 一般来说, 都会有一个webpack.config.js的webpack配置文件.下面的代码就是一个简单的webpack的配置, 麻雀虽小五脏俱全.

var debug = process.env.NODE_ENV !== "production"; //是否是测试环境
var webpack = require('webpack'); //导入webpack包
var path = require('path');

module.exports = { //导出 webpack固定写法
 context: path.join(__dirname),
 devtool: debug ? "inline-sourcemap" : null, //是否使用map工具, 用于浏览器debug
 entry: "./src/js/root.js", //打包的实体
 module: {
  loaders: [ //加载的配置
   {
    test: /\.js?$/,
    exclude: /(node_modules)/,
    loader: 'babel-loader',
    query: {
     presets: ['react', 'es2015'], //添加预处理器
     plugins: ['react-html-attrs'], //添加组件的插件配置
    }
   },
   { test: /\.css$/, loader: 'style-loader!css-loader' },
   {
    test: /\.less$/,
    loader: "style!css!less"
   }
  ]
 },
 output: { //输出的路径及文件名
  path: __dirname,
  filename: "./src/bundle.js"
 },
 plugins: debug ? [] : [ //一些插件
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.OccurenceOrderPlugin(),
  new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
 ],
};

webpack主要包括entry, module, output, plugins四大类, 官方文档说的已经很清楚了, 想要进一步的学习,请翻阅官方文档, 如果不想折腾直接拷贝上述代码即可.

相较gulp, webpack在打包方面更为精简, 这也是流行的原因吧, 但光看上面的文件, 的确也是简单, 但是还有进一步改善的空间.

package.json

对于npm的介绍我就不多说了, 我们直接来看文件.

{
 "name": "webpack",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": { //命令行工具
  "test": "echo \"Error: no test specified\" && exit 1",
  "watch": "webpack --progress --watch",
  "start": "webpack-dev-server --open --config webpack.dev.js",
  "build": "webpack --config webpack.prod.js"
 },
 "keywords": [],
 "author": "",
 "license": "ISC",
 "devDependencies": { //开发环境依赖
  "babel-loader": "^7.1.2",
  "clean-webpack-plugin": "^0.1.16",
  "css-loader": "^0.28.7",
  "csv-loader": "^2.1.1",
  "file-loader": "^0.11.2",
  "html-webpack-plugin": "^2.30.1",
  "json-loader": "^0.5.7",
  "lodash": "^4.17.4",
  "style-loader": "^0.18.2",
  "uglifyjs-webpack-plugin": "^0.4.6",
  "webpack": "^3.6.0",
  "webpack-dev-middleware": "^1.12.0",
  "webpack-dev-server": "^2.8.2",
  "webpack-merge": "^4.1.0",
  "xml-loader": "^1.2.1"
 },
 "dependencies": { //生产环境依赖
  "babel-plugin-import": "^1.5.0",
  "babel-plugin-react-html-attrs": "^2.0.0",
  "babel-preset-es2015": "^6.24.1",
  "babel-preset-react": "^6.24.1",
  "babelify": "^7.3.0",
  "react": "^15.6.1",
  "react-dom": "^15.6.1",
  "react-mixin": "^4.0.0",
  "react-router": "^4.2.0"
 }
}

命令行工具就是npm run build等于执行了webpack --config webpack.prod.js, 而npm start 等于执行了webpack-dev-server --open --config webpack.dev.js.简单易懂吧.

在项目依赖中, 哦们加了很多的插件和loader, 都是用来搭建webpack的, 官方文档的教程中都会讲到, 值得注意的就是webpack-merge这个包, 这个包可以让我们生产环境和开发环境很好的隔离配置, 我们看看怎么做呢?

首先我们需要将之前的webpack.config.js分成三个文件 --- webpack.common.js, webpack.dev.js, webpack.prod.js.

webpack.common.js

这个是webpack的共同配置, 总体和之前看到的大同小异, 我们主要是导入了两个插件, 一个是清除插件, 一个是创建html的插件.

const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
 entry: './src/index.js',
 plugins: [
  new CleanWebpackPlugin(['dist']),
  new HtmlWebpackPlugin({title: 'webpack'}),
  new webpack.HashedModuleIdsPlugin()
 ],
 output: {
  filename: '[name].[chunkhash].js',
  path: path.resolve(__dirname, 'dist')
 },
 module: {
  rules: [
   {
    test: /\.js?$/,
    exclude: /(node_modules)/,
    loader: 'babel-loader',
    query: {
     presets: [
      'react', 'es2015'
     ],
     plugins: ['react-html-attrs']
    }
   },
   {
    test: /\.css$/,
    use: ['style-loader', 'css-loader']
   }, {
    test: /\.(png|svg|jpg|gif)$/,
    use: ['file-loader']
   }, {
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    use: ['file-loader']
   }, {
    test: /\.(csv|tsv)$/,
    use: ['csv-loader']
   }, {
    test: /\.xml$/,
    use: ['xml-loader']
   }
  ]
 }
};

rules配置中我们也就是将一些可能用到的文件也配置到webpack中来, babel-loader这种如果要讲还可以再开一篇, 其实就是个js的兼容性工具, 这样理解就可以了.

webpack.dev.js

webpack开发环境的配置, 非常简单, 就是用了之前讲的webpack-merge工具, 就和git一样, 合并了webpack.common.js的配置外新加了可以进行调试的inline-source-map工具, 以及热更新的内容索引.

const merge = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
 devtool: 'inline-source-map',
 devServer: {
  contentBase: './dist'
 }
});

webpack.prod.js

webpack生产环境的配置, 新加了一个压缩插件以及环境配置的插件, 这里的开发工具和开发还款下的有所不同, 具体可直接看官方文档.

const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');

module.exports = merge(common, {
 devtool: 'source-map',
 plugins: [
  new UglifyJSPlugin({sourceMap: true}),
  new webpack.DefinePlugin({
   'process.env': {
    'NODE_ENV': JSON.stringify('production')
   }
  })
 ]
});

terminal

这样我们就配置完成啦, 我们在终端上输入看下效果:

cd ../ && npm i

首先我们进入到目录下并进行node包的安装.

npm run build

MacBook-Pro-15:webpack zhushuangquan$ npm run build

> webpack@1.0.0 build /Users/zhushuangquan/Documents/code/webpack
> webpack --config webpack.prod.js

clean-webpack-plugin: /Users/zhushuangquan/Documents/code/webpack/dist has been removed.
Hash: 85b65f54ef1436b295a5
Version: webpack 3.6.0
Time: 1148ms
              Asset    Size Chunks       Chunk Names
  main.014ac9aa420264da48eb.js 671 bytes    0 [emitted] main
main.014ac9aa420264da48eb.js.map  6.47 kB    0 [emitted] main
           index.html 197 bytes     [emitted] 
[lVK7] ./src/index.js 184 bytes {0} [built]
Child html-webpack-plugin for "index.html":
   1 asset
  [3IRH] (webpack)/buildin/module.js 517 bytes {0} [built]
  [DuR2] (webpack)/buildin/global.js 509 bytes {0} [built]
    + 2 hidden modules

我们可以看到已经打包好的文件:

main.014ac9aa420264da48eb.js

!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var t={};n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n(n.s="lVK7")}({lVK7:function(e,n,t){"use strict";document.body.appendChild(function(){var e=document.createElement("div");return e.innerHTML="Hello webpack",e}())}});
//# sourceMappingURL=main.014ac9aa420264da48eb.js.map

我们可以看到在webpack的打包和压缩下, 代码已经基本不可读了. 所以我们需要加上之前的调试插件, 以便生产环境出现bug后的补救.

npm start

MacBook-Pro-15:webpack zhushuangquan$ npm start

> webpack@1.0.0 start /Users/zhushuangquan/Documents/code/webpack
> webpack-dev-server --open --config webpack.dev.js

clean-webpack-plugin: /Users/zhushuangquan/Documents/code/webpack/dist has been removed.
Project is running at http://localhost:8080/
webpack output is served from /
Content not from webpack is served from ./dist
webpack: wait until bundle finished: /
Hash: 06f20ec519d58fbd5c28
Version: webpack 3.6.0
Time: 1460ms
            Asset    Size Chunks          Chunk Names
main.5eb4d4e3f458c49658a2.js   852 kB    0 [emitted] [big] main
         index.html 197 bytes     [emitted]     
[6Um2] (webpack)/node_modules/url/util.js 314 bytes {0} [built]
[8o/D] (webpack)-dev-server/client/overlay.js 3.71 kB {0} [built]
[HPf+] (webpack)/node_modules/url/url.js 23.3 kB {0} [built]
[Lx3u] (webpack)/hot/log.js 1.04 kB {0} [optional] [built]
[Sj28] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {0} [built]
[TfA6] (webpack)/hot nonrecursive ^\.\/log$ 170 bytes {0} [built]
[U2me] (webpack)/hot/emitter.js 77 bytes {0} [built]
[V3KU] (webpack)-dev-server/client/socket.js 1.04 kB {0} [built]
[cMmS] (webpack)-dev-server/client?http://localhost:8080 7.27 kB {0} [built]
[gqsi] (webpack)-dev-server/node_modules/loglevel/lib/loglevel.js 7.74 kB {0} [built]
  [0] multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js 40 bytes {0} [built]
[gt+Q] (webpack)-dev-server/node_modules/ansi-regex/index.js 135 bytes {0} [built]
[lVK7] ./src/index.js 184 bytes {0} [built]
[p7Vd] (webpack)/node_modules/punycode/punycode.js 14.7 kB {0} [built]
[pEPF] (webpack)/node_modules/querystring-es3/index.js 127 bytes {0} [built]
  + 73 hidden modules
Child html-webpack-plugin for "index.html":
   1 asset
  [3IRH] (webpack)/buildin/module.js 517 bytes {0} [built]
  [DuR2] (webpack)/buildin/global.js 509 bytes {0} [built]
  [M4fF] ./node_modules/lodash/lodash.js 540 kB {0} [built]
  [a/t9] ./node_modules/html-webpack-plugin/lib/loader.js!./node_modules/html-webpack-plugin/default_index.ejs 538 bytes {0} [built]
webpack: Compiled successfully.

我们可以看到打开了一个内容为Hello webpack的网页在8080端口, 当我们修改了文件时候网页会自动刷新.

知识点:

回到我们刚才的package.json的命令行配置来看.

"scripts": { //命令行工具
  "test": "echo \"Error: no test specified\" && exit 1",
  "watch": "webpack --progress --watch",
  "start": "webpack-dev-server --open --config webpack.dev.js",
  "build": "webpack --config webpack.prod.js"
 },
  • 上面的npm run build => webpack => webpack.prod.js, 就是执行了生产环境的配置的打包命令.
  • 上面的npm start => webpack-dev-server --open => webpack.dev.js, 就是执行了开发环境配置的服务端命令.
  • --config是用于执行webpack配置文件的命令, 而默认为webpack.config.js.
  • webpack命令就是和之前的gulp的逻辑相似, 将entry实例复制到output路径的逻辑. 当然还伴随着一系列的操作.
  • webpack-dev-server --open命令是打开服务器并进行热加载的用途.

以上就是webpack的使用及逻辑, 并没有想象中的复杂吧, 甚至可以说是简单, 实测一天即可入门webpack.

由于webpack的配置是固定代码, 我已经打包上传github, 需要的同学可以进行下载.

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

Javascript 相关文章推荐
用document.documentElement取代document.body的原因分析
Nov 12 Javascript
javascript json2 使用方法
Mar 16 Javascript
基于jquery的修改当前TAB显示标题的代码
Dec 11 Javascript
获取css样式表内样式的js函数currentStyle(IE),defaultView(FF)
Feb 14 Javascript
浅析js封装和作用域
Jul 09 Javascript
jquery实现的下拉和收缩效果示例
Aug 21 Javascript
jquery.validate提示错误信息位置方法
Jan 22 Javascript
js判断复选框是否选中及选中个数的实现代码
May 30 Javascript
jqGrid用法汇总(全经典)
Jun 28 Javascript
bootstrap常用组件之头部导航实现代码
Apr 20 Javascript
vue axios 在页面切换时中断请求方法 ajax
Mar 05 Javascript
vue-form表单验证是否为空值的实例详解
Oct 29 Javascript
vue webuploader 文件上传组件开发
Sep 23 #Javascript
jQuery使用zTree插件实现可拖拽的树示例
Sep 23 #jQuery
一个有意思的鼠标点击文字特效jquery代码
Sep 23 #jQuery
JQuery用$.ajax或$.getJSON跨域获取JSON数据的实现代码
Sep 23 #jQuery
VsCode新建VueJs项目的详细步骤
Sep 23 #Javascript
详解webpack + vue + node 打造单页面(入门篇)
Sep 23 #Javascript
JavaScript定义函数的三种实现方法
Sep 23 #Javascript
You might like
Php做的端口嗅探器--可以指定网站和端口
2006/10/09 PHP
Thinkphp多文件上传实现方法
2014/10/31 PHP
PHP通过插入mysql数据来实现多机互锁实例
2014/11/05 PHP
php技术实现加载字体并保存成图片
2015/07/27 PHP
简单谈谈php浮点数精确运算
2016/03/10 PHP
PHP分页初探 一个最简单的PHP分页代码的简单实现
2016/06/21 PHP
PHP性能分析工具xhprof的安装使用与注意事项
2017/12/19 PHP
Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析
2020/04/14 PHP
PHP优化之批量操作MySQL实例分析
2020/04/23 PHP
用js实现手把手教你月入万刀(转贴)
2007/11/07 Javascript
JS随机漂浮广告代码具体实例
2013/11/19 Javascript
JavaScript实现非常简单实用的下拉菜单效果
2015/08/27 Javascript
ionic cordova一次上传多张图片(类似input file提交表单)的实现方法
2016/12/16 Javascript
JS数字千分位格式化实现方法总结
2016/12/16 Javascript
livereload工具实现前端可视化开发【推荐】
2016/12/23 Javascript
Vue 过渡(动画)transition组件案例详解
2017/01/22 Javascript
使用ECharts实现状态区间图
2018/10/25 Javascript
如何在现代JavaScript中编写异步任务
2021/01/31 Javascript
使用graphics.py实现2048小游戏
2015/03/10 Python
python在windows下实现ping操作并接收返回信息的方法
2015/03/20 Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
2018/05/19 Python
Python处理时间日期坐标轴过程详解
2019/06/25 Python
Django实现文件上传和下载功能
2019/10/06 Python
Python实现数值积分方式
2019/11/20 Python
如何基于python操作excel并获取内容
2019/12/24 Python
python实现五子棋程序
2020/04/24 Python
Python利用Pillow(PIL)库实现验证码图片的全过程
2020/10/04 Python
python中entry用法讲解
2020/12/04 Python
Clarks英国官方网站:全球领军鞋履品牌
2016/11/26 全球购物
P/Invoke是什么
2015/07/31 面试题
群众路线教育实践活动批评与自我批评
2014/09/15 职场文书
2014年市场部工作总结
2014/11/25 职场文书
入党介绍人意见范文
2015/06/01 职场文书
升学宴学生致辞
2015/07/27 职场文书
初中英语教学反思范文
2016/02/15 职场文书
Linux中各个目录的作用与内容
2022/06/28 Servers