Vue学习-模块化开发
多个js文件造成的问题
全局变量同名,造成多人开发变量被其他人修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="aaa.js"></script>
<script src="bbb.js"></script>
<script src="mmm.js"></script>
</body>
</html>
// 小明开发
// aaa.js
var name = 'xiaoming';
var age = 22;
function sum(num1, num2) {
return num1 + num2;
}
var flag = true;
if (flag) {
console.log(sum(10, 20)); // 30
}
// 小红开发
// bbb.js
var name = 'xiaohong';
var flag = false;
console.log(name); // xiaohong
// mmm.js
if (flag) {
console.log('小明是天才'); // 这里是不会打印出来的
}
匿名函数的解决方案(原始雏型)
函数具有自己的作用域
// 小明开发
// aaa.js
;
var moduleA = (function() {
var obj = {};
var name = 'xiaoming';
var age = 22;
function sum(num1, num2) {
return num1 + num2;
}
var flag = true;
if (flag) {
console.log(sum(10, 20));
}
obj.flag = flag;
obj.sum = sum;
console.log(obj);
return obj;
})();
// 小红开发
// bbb.js
;
var moduleB = (function() {
var obj = {};
var name = 'xiaohong';
var flag = false;
console.log(name);
obj.flag = flag;
return obj;
})();
// mmm.js
;(function() {
if (moduleA.flag) {
console.log('小明是天才'); // 能够正常打印
}
})();
常见的模块化规范
-
CommonJs
模块化的两个核心模块:导出和导入
CommonJs中的导出
module.exports = { flag: true, test(a, b) { return a + b; }, demo(a, b) { return a * b; } }CommonJs中的导入
let { test, demo, flag } = require('moduleA'); // moduleA为导出的文件路径 -
AMD
-
CMD
-
ES6中的Modules
ES6中新增了2个关键字: export import
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
// 这里要添加type="module"
<script src="aaa.js" type="module"></script>
<script src="bbb.js" type="module"></script>
<script src="mmm.js" type="module"></script>
</body>
</html>
aaa.js
// 小明开发 aaa.js
let name = 'xiaoming';
let age = 18;
let flag = true;
function sum(num1, num2) {
return num1 + num2;
}
if (flag) {
console.log(sum(10, 20));
}
// 1. 导出方式1
export {
flag, sum
}
// 2. 导出方式2
export var num1 = 1000;
export var height = 1.88;
// 3. 导出函数/类
export function mul(num1, num2) {
return num1 * num2;
}
export class Person {
run() {
console.log('run');
}
}
// 4. export default
// 某些情况下,一个模块包含某个功能,我们并不希望给这个功能命名,而让导入者可以自己来命名,这个时候可以使用export default
// export default在同一个模块中只能存在一个,不允许存在多个
const address = 'beijing';
export default address;
bbb.js
// 小红开发 bbb.js
let name = '小红';
let flag = false;
mmm.js
import { flag, sum } from './aaa.js'
if (flag) {
console.log('小明是天才');
console.log(sum(100 , 200));
}
import { num1, height } from './aaa.js'
console.log('num1 ', num1);
console.log('height ', height);
import { mul, Person } from './aaa.js'
console.log(mul(100, 100));
const p = new Person();
p.run();
import add from './aaa.js'
console.log(add);
// 通配符
import * as aaa from './aaa.js'
console.log(aaa.flag);
console.log(aaa.height);
webpack
认识webpack
模块化 打包 工具
模块化:
webpack其中的一个核心就是帮助我们能够进行模块化开发,并且帮助我们处理模块间的依赖
而且不仅仅是js文件,我们的css,图片,json文件等等在webpack中都可以当作模块
打包:
就是将webpack中的各种资源模块进行打包合并成一个或者多个包
并且在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss转化成css,将es6语法转化成es5语法等等操作
webpack的安装
// 查看node版本
node -v
// 全局安装webpack
npm install webpack@3.6.0 -g
webpack的起步
main.js
const { sum, mul } = require('./mathUtil.js');
console.log(sum(20, 30));
console.log(mul(20, 30));
mathUtil.js
function sum(num1, num2) {
return num1 + num2;
}
function mul(num1, num2) {
return num1 * num2;
}
module.exports = {
sum, mul
}
webpack打包命令
webpack ./src/main.js ./dist/bundle.js
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./dist/bundle.js"></script>
</body>
</html>
打包出来的bundle.js
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
const { sum, mul } = __webpack_require__(1);
console.log(sum(20, 30));
console.log(mul(20, 30));
/***/ }),
/* 1 */
/***/ (function(module, exports) {
function sum(num1, num2) {
return num1 + num2;
}
function mul(num1, num2) {
return num1 * num2;
}
module.exports = {
sum, mul
}
/***/ })
/******/ ]);
webpack的配置
将webpack ./src/main.js ./dist/bundle.js命令缩写成webpack
-
npm init -
创建webpack.config.js文件
其中,__dirname指的是本文件所在的绝对路径,
entry指的是项目的入口文件,output指的是项目的出口文件,path是出口文件的路径,filename是出口文件的名称,这样配置了以后就可以使用webpack命令代替webpack ./src/main.js ./dist/bundle.js
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
// 动态获取路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
-
使用
npm run build命令代替webpacknpm init之后会自动生成一个package.json文件,在package.json文件的scripts中添加配置"build": "webpack"便可以使用npm run build命令代替webpack,使用npm run build会优先使用本地的webpack{ "name": "meetwebpack", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack" }, "author": "", "license": "ISC" } -
本地安装webpack
npm install webpack@3.6.0 --save-dev
loader的使用
loader的使用过程
- 通过npm安装需要的loader
- 在webpack.config.js中的modules关键字下面进行配置
css文件的处理
npm install css-loader@2.0.2 --save-dev
npm install style-loader --save-dev
module: {
rules: [
{
test: /\.css$/,
// css-loader只负责css文件的加载,style-loader负责样式的渲染
use: ['style-loader', 'css-loader']
}
]
}
less文件的处理
npm install less less-loader@5.0.0 --save-dev
{
test: /\.less$/i,
loader: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
}
图片等文件的处理
npm install url-loader@4.1.1 --save-dev
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
}
当图片大小超过limit的时候,会报错,需要使用file-loader
npm install file-loader@3.0.1 --save-dev
运行之后会出现图片请求不到的情况,是因为图片以文件的形式存放在dist目录下,需要在webpack.config.js中添加配置:publicPath: 'dist/'
const path = require('path');
module.exports = {
entry: './src/main.js',
output: {
// 动态获取路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
// css-loader只负责css文件的加载,style-loader负责样式的渲染
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/i,
loader: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
}, {
test: /\.(png|jpg|gif|jepg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8912,
}
}
]
}
]
}
}
图片文件名的处理:
增加name配置
{
test: /\.(png|jpg|gif|jepg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8912,
name: 'img/[name].[hash:8].[ext]'
}
}
]
}
ES6语法的处理loader
npm install --save-dev babel-loader@7.1.5 babel-core@6.26.3 babel-preset-es2015@6.24.1
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
webpack中配置vue
npm install vue --save
在webpack.config.js中添加配置,指定使用runtime-compiler版本(默认是runtime-only版本)
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
template和el共存时,template中的内容,会把el挂载的dom中的所有元素替换为template中的内容
使用.vue文件
npm install vue-loader@13.0.0 vue-template-compiler --save-dev
注意vue-template-compiler和vue的版本要保持一致
可以不加.vue扩展名,添加extensions配置
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
plugin的使用
版权信息插件
const webpack = require('webpack');
plugins: [
new webpack.BannerPlugin('最终版权归xx所有')
]
HtmlWebpackPlugin
不是webpack自带的插件,需要手动安装
npm install html-webpack-plugin@3.2.0 --save-dev
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new webpack.BannerPlugin('最终版权归xx所有'),
new HtmlWebpackPlugin({
template: 'index.html'
})
]
压缩js插件
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
plugins: [
new webpack.BannerPlugin('最终版权归xx所有'),
new HtmlWebpackPlugin({
template: 'index.html'
}),
new UglifyjsWebpackPlugin()
]
搭建本地服务器
npm install webpack-dev-server@2.9.3 --save-dev
devServer: {
contentBase: './dist',
inline: true // 实时监听
}
// 运行起来
./node_modules/.bin/webpack-dev-server
或者在package.json中配置
// --open自动打开
"dev": "webpack-dev-server --open"
npm run dev
webpack配置文件的分离
npm install webpack-merge@4.1.5 --save-dev
base.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
// const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
// 动态获取路径
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
// publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
// css-loader只负责css文件的加载,style-loader负责样式的渲染
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/i,
loader: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
}, {
test: /\.(png|jpg|gif|jepg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8912,
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
resolve: {
extensions: ['.js', '.css', '.vue'],
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new webpack.BannerPlugin('最终版权归xx所有'),
new HtmlWebpackPlugin({
template: 'index.html'
}),
// new UglifyjsWebpackPlugin()
],
// devServer: {
// contentBase: './dist',
// inline: true // 实时监听
// }
}
prod.config.js
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');
module.exports = webpackMerge(baseConfig, {
plugins: [
new UglifyjsWebpackPlugin()
]
})
dev.config.js
const webpackMerge = require('webpack-merge');
const baseConfig = require('./base.config');
module.exports = webpackMerge(baseConfig, {
devServer: {
contentBase: './dist',
inline: true // 实时监听
}
})
Package.json
这里通过--config来配置build和dev的路径
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --open --config ./build/dev.config.js"
},