基于webpack搭建前端工程的思考

蚊子前端博客
发布于 2017-10-13 20:03
webpack是一个前端打包构建工具, 功能强大,本篇也是基于webpack简单探讨下前端的工程化

前端工程化的概念和思想早就已讨论过,并且之前也用requireJS和seaJS实现过,同时,在2015年,ECMAscript也发布了js的正式版ES6。在ES6(ES2015)中,实现了标准上的统一,从底层上实现了模块化的支持。不过由于浏览器发展的滞后性,尤其是IE,ES6中很多的属性依然是不支持的,因此也就出现了第三方工具babel,将ES6语法转换为浏览器统一支持的ES5。

在上一篇文章中,我们对webpack也有个简单的了解了,在webpack中,一切皆资源,CSS,JS,图片等都可以作为资源处理。将资源进行分类,模块化的管理,适配到不同的页面。

1. 资源管理

项目的工程化,最主要的就是对资源的管理,对整个项目进行思考后,如何拆分资源。对于业务上的组件,我们可以放到components的目录中,然后对外暴露接口。

webpack对CommonJS,AMD和ES6的模块化都有非常好的支持,不过我们最好还是安装ES6的标准来写代码。webpack编译打包后,都会打包到一个文件中。同时,webpack让我们更加专注逻辑代码的编写,而不用关心代码是如何被引用的。

关于exportimport具体如何使用,可以参考阮一峰的文章 Module 的语法

2. 本地开发环境

一个项目的目录结构可以是这样的:

COPYTEXT

`-out # 编译后 `-src # 原文件 `---css `---img `---js `---components # 组件 `-entry.js `-package.json `-webpack.config.js # 配置文件 `-index.html

为了方便本地的开发和调试,我们使用webpack-dev-server搭建一个本地服务:

COPYBASH

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

下载安装完成后,我这里对应的版本号是:

COPYJSON

{ "webpack": "^2.7.0", "webpack-dev-server": "^2.9.1" }

本来安装网上的教程配置server时,各种出错,后来就一点点注释,看看是哪里配置错了,结果只能把整个devServer的配置全部注释掉。

启动服务:

COPYBASH

webpack-dev-server --open -hot

程序会自动打开浏览器http://localhost:8080。但是,这里有个问题,页面该怎么引入静态资源呢,其实静态资源的路径就是在webpack.config.js中的output中配置的:

COPYJAVASCRIPT

output : { publicPath: '/dist/', filename: '[name].js' }

那么src中的静态资源就会编译到 /dist/ 的路径中了,页面中直接引用就行了。不过,当我们查看项目目录时,却没有 dist 目录,其实在使用webpack-dev-server启动本地服务后,编译的 /dist/ 目录是只存在在内存中的,服务关闭后,dist目录就不存在了。

3. webpack的配置

在之前的文章中,我们把webpack的配置写到了webpack.config.js中。编译时,默认就是调用该文件中的配置。但是,从代码开发到部署到线上,要经历3个环境: 本地开发环境、测试环境与正式环境。

不过我们这里,只配置本地开发环境和测试环境,正式环境与测试环境的代码已经一样了,只是正式环境是另一套发布流程了:

  • webpack.base.config.js 基础配置

  • webpack.dev.config.js 本地开发环境

  • webpack.pro.config.js 测试环境

webpack.base.config.js :

COPYJAVASCRIPT

var webpack = require('webpack'), path = require('path'), ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry : function(){ return { index : './src/index.js' } }, output : { publicPath: '/dist/', filename: '[name].js' }, // 新添加的module属性 module: { rules: [ { test: /\.js?$/, loader: "babel-loader", exclude: /(node_modules|bower_components)/, options: { presets: ['es2015'] } }, { test: /\.css$/, // loader: "style!css" use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }, { test: /\.(jpg|png)$/, loader: "url?limit=8192" }, { test: /\.scss$/, // loader: "style!css!sass" use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader!sass-loader" }) } ] }, plugins : [] }

webpack.dev.config.js :

COPYJAVASCRIPT

const base = require('./webpack.base.config'), ExtractTextPlugin = require("extract-text-webpack-plugin"); const config = Object.assign({}, base, { output: { publicPath: '/dist/', filename: '[name].js' }, plugins : [ new ExtractTextPlugin({filename:"[name].css", disable: false, allChunks: true}) ] }); module.exports = config;

webpack.pro.config.js :

COPYJAVASCRIPT

const base = require('./webpack.base.config'), ExtractTextPlugin = require("extract-text-webpack-plugin"); const config = Object.assign({}, base, { output: { publicPath: './build/', filename: '[name]-[chunkhash:8].js' }, plugins : [ new ExtractTextPlugin({filename:"[name].css", disable: false, allChunks: true}), new webpack.BannerPlugin('created at '+(new Date()).toLocaleString()) ] }); module.exports = config;

webpack.base.config.js是基础文件,不直接调用,我们在package.json中把命令简化一下:

COPYJSON

"scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --config config/webpack.dev.config.js", "build": "cross-env NODE_ENV=production webpack --progress --hide-modules --config config/webpack.pro.config.js" }

运行npm run dev命令时,调用的是webpack.dev.config.js,进行本地开发;运行npm run build,调用webpack.pro.config.js,进行预发布编译。

4. 总结

因为项目的难易程度,部署代码、测试发布的流程都不一样,在webpack的开发过程中,也依然需要遵循公司的标准进行自动化的整合。

标签:
阅读(529) 评论(0)

公众号:

qrcode

微信公众号:前端小茶馆