从模块化演进到webpack打包,再到Vue单文件组件开发
前端代码规模增长带来的挑战
早期JavaScript仅用于简单的表单验证或动画效果,代码量不大。随着AJAX技术普及,前后端分离成为主流,前端需要处理的任务激增,代码量也随之膨胀。为了管理日益复杂的代码,开发者通常将代码拆分到多个JS文件中维护。然而,这种方式仍存在全局变量冲突等隐患。
利用闭包解决命名冲突
每个模块的代码封装在闭包内,闭包返回需要共享的数据,并用变量接收。这样只需确保每个文件的顶层变量名不重复即可。
let moduleXXX = (function() {
// 模块逻辑
return { /* 共享内容 */ };
})();
模块化规范
CommonJS
导出:
module.exports = {
// 模块内容
};
导入:
let { a, b, c } = require('moduleA');
// 等价写法
let moduleA = require('moduleA');
let a = moduleA.a;
let b = moduleA.b;
let c = moduleA.c;
ES6 Module
使用ES6模块时,需在HTML中设置<script type="module">,每个模块拥有独立作用域,避免命名冲突。通过export导出内容:
export { a, b, c };
在其他模块中导入:
import { a, b, c } from 'module.js';
也可在定义时直接导出:
export var num = 10;
export default允许导出默认值,导入时可自定义名称,一个模块只能有一个default:
// 导出
export default function() {}
// 导入
import myFunc from 'module.js';
批量导入可用:
import * as all from 'module.js';
其他规范:AMD、CMD
webpack基础应用
什么是webpack
webpack是一个现代JavaScript应用的静态模块打包工具。它从入口文件开始,递归构建依赖关系图,最终将所有模块打包成一个或多个bundle。
与grunt/gulp的区别
Grunt和Gulp侧重于自动化流程(如压缩、合并),模块化不是核心。webpack则专注于模块化开发管理,自动化是附带功能。
安装
# 全局安装(以3.6.0为例,因Vue CLI2依赖此版本)
npm install webpack@3.6.0 -g
# 验证安装
webpack --version
# 局部安装(作为开发依赖)
npm install webpack@3.6.0 --save-dev
当package.json的scripts中定义了webpack命令时,优先使用本地webpack。
命令行打包
webpack main.js bundle.js
webpack会自动分析main.js的依赖并处理。
使用配置文件打包
创建webpack.config.js:
var path = require('path');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
}
};
在package.json中添加脚本:
"scripts": {
"build": "webpack"
}
然后执行npm run build。
各种loader的使用
在webpack配置的module.rules中定义转换规则。
CSS
npm install --save-dev css-loader style-loader
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
Less
npm install --save-dev less-loader less
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
}
Sass
npm install --save-dev sass-loader node-sass
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
图片
npm install --save-dev url-loader file-loader
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 13000, // 小于此值转base64
name: 'images/[name]-[hash:8].[ext]'
}
}]
}
图片路径可通过output.publicPath指定发布目录。
ES6语法转换
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
在webpack中使用Vue
安装Vue:npm install vue --save。
在入口JS中:
import Vue from 'vue';
new Vue({
el: '#app',
});
HTML中需有一个id="app"的div。
打包后发现报错?原因是Vue有两种构建版本:
- runtime-only:不支持template选项(无编译器)
- runtime-compiler:支持template(包含编译器)
需在webpack配置中指定版本:
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
抽取Vue模板
直接使用Vue实例会导致代码臃肿。更好的做法是定义组件并抽离。
创建App组件,在Vue实例中使用template引入。然后将组件定义放入独立JS文件,在入口处导入。
封装.vue文件
将组件抽离为JS文件仍不够直观。.vue文件允许将template、script、style集中管理,清晰且易于维护。
安装依赖:
npm install vue-loader vue-template-compiler --save-dev
添加webpack规则:
{
test: /\.vue$/,
use: ['vue-loader']
}
若vue-loader版本高于13,需额外配置插件。可降级至13版本:"vue-loader": "^13.0.0"。