模块化思想

// 1最早期就只是html和css处理网页

// 2发明一种语言来操作html和css js

// 3早期只是在html文件里直接在script标签里写一些脚本代码

// 4随着Ajax的出现,慢慢形成了前后端的分离

// 5客户端需要完成的事情越来愈多,代码量与日俱增

// 6为了应对代码量的增加,通常会将代码组织在多个js文件中,进行维护,就会出现许多问题

首先,当我们编写代码时,不通过模块化的思想想要引入一个js,通常是在html文件中创建一个script标签,引入我们需要的js,如果我们引入的是自己手写的js,在过个js文件中,或者多人合作开发时候,很容易发生变量重名的冲突。

// 变量命名冲突
// a.js 小明开发的
var a = true; // b.js 小红开发的
var a = false // index.html 中同时引入a.js、b.js后,小明记得自己的a变量是true //c.js //小明继续开发
if(a){
console.log('我定义的a变量是true')
}
这样就报错了,小明不知道自己的变量被修改了,所以模块化思想之前很容易造成变量命名冲突的问题 所以必须解决这种问题,通过一些方法去避免这些错误,比如:匿名函数,但匿名函数又会发生每个js文件中的作用域私有,而代码不可发生复用的问题,因此又需要想方法解决,例如: // a.js
var moudleA = (function() {
const obj = {}
const a = '我是模块A中的变量a' obj.a = a
return obj // 将匿名函数中的变量暴露出去,实现代码复用
})() // b.js
(function() {
console.log(moudleA.a) // 引用a中的变量,并且解决变量重名
})() // index.html 中同时引入a.js、b.js
并且,这种导入方式对js插入顺序依赖性很强,一般公司多人开发,不同的开发人员引入不同的js文件,插入位置错误发生的报错。
但不可否认,通过匿名函数将变量暴露出去这种方式,就是最基础的模块封装。当然现在对于前端模块化已经有了很多规范:Common.js、AMD、CMD、ES6中的Modules。
总结:
0代码复杂化带来的问题
1为什么需要模块化
2模块化方案
3es6之前的方案
4处理模块依赖,整合打包
5不仅仅能处理js,其他html,css,图片,json也可以模块化处理

什么是webpack?

简单通俗的说webpack就是一个前端自动化工具 模块 打包

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

它是依赖于node环境的

官网:

https://www.webpackjs.com/concepts/

搭建vuecli

1先安装node环境

node -v npm -v 查看版本

2新建文件夹vuecli,并初始化

npm init -y

文件夹是中文名的话,这样会报错,需要npm init回车然后填写名称,其他信息一路回车即可,然后熟悉的package.json两兄弟文件就在根目录中出来了

npm安装是缩写模式, 简单说下:

-D 为 --save-dev 开发环境中使用

-S 为 --save 生产环境中使用

-g 为 --global 全局安装





安装npm i webpack webpack-cli -D 我之前已经安装过全局的了

为啥在项目中还要安装本地webpack,而不是直接用全局的?

当你全局安装了webpack, 你使用指令webpack打包又先调用的是你全局的webpack。 毕竟你今天安装的webpack是这个版本,不能保证以后谁拿你代码一运行调用他电脑下载的webpack版本,beng,满屏飘红就出来了。因为当时做项目时的webpack版本不一样,当你克隆下来时,你就会把当时的webpack版本也克隆下来,再安装时候,就不会出现版本冲突了 所以保险点,项目都安装自己的webpack,版本不会冲突。

3测试webpack打包使用

新建文件夹dist和文件mian.js和index.html



index.html文件引入打包后的文件 命名为bundle.js如图



maian.js输入测试代码



在终端输入命名 版本不同命令输入也不同 注意

webpack main.js -o dist/bundle.js 会生成如图



测试代码也能成功



注意:此时的webpack命令是调用全局的webpack

当你安装好webpack后执行打包指令后, 执行"webpack xxxx"时要注意,此时如果你安装了全局webpack,任然调用的是你全局的而不是项目自己的,你项目调用自己的webpack指令应该是./node_modules/.bin/webpack xxxxx

为了解决该问题,我们可以添加webpack.config.js

4添加webpack.config.js文件

// webpack.config.js
const path = require("path") //node自带模块 引入路径模块
module.exports = {
entry: "./main.js", // 入口
output: {
path: path.resolve(__dirname, 'dist'), // 出口。必须为绝对路径,所以借助node的path模块 __dirname保存的是当前文件的路径
filename: 'bundle.js' // 打包后文件名
},
}
// 意思就是:我根目录有个main.js文件,里面导入了好多东西,帮我打包到我目录里面的dist文件下bundle.js文件里
// package.json
并且还需要更改一下package.json文件中的scripts属性
{
...
scripts: {
...
"build": "webpack" // build可以随便取,如: 叫xxx,终端运行 npm run xxx即可
//执行脚本"build": "webpack"时候,它会优先找本地的webpack,
//只要实在终端直接输入webpack打包都是使用的全局的,所以为了解决这个问题,用脚本这样会优先找本地的
}
...
} // 意思: 以后我直接在终端运行一个叫build的指令去调用webpack打包, 并且通过该指令, 会自动帮我们调用开发环境中的webpack打包

当运行npm run build时,webpack会看看我们根目录是不是有一个叫webpack.config.js的文件,然后读取运行其中的配置。

弄完这一步,最后将index.html中引入的main.js改为bundle.js后,我们可以愉快的将各个js文件当成模块,各种require、import、、、,尽情导入导出

比如,我这里在src文件夹中新建js文件夹,添加info.js、mainUnit.js然后再main.js中引入并使用

loader的使用

webpack并不能识别许多文件类型,我们需要通过各种各样的loader,来帮webpack识别。

接下来做css相关,图片相关的loader,新建文件如下



在main.js中引入 require("xxx.css")或者import "xxx.less",然后一运行报错

5引入css和less相关loader

进入webpack官网, 点击导航中的LOADERS,点击左边导航的样式,然后就可以根据需求对照文档安装和配置你需要的样式相关loader了

我这里安装css和less相关的loader,npm i style-loader css-loader less-loader less -D 因为loader基本用于开发环境, 所以安装一般都为--save-dev

// webpack.config.js
module.exports = {
...
module:{
rules: [
{
test: /\.css$/,
// css-loader 只负责解析css,并不负责插入样式到页面
// style-loader 负责将样式插入页面中
// 使用多个loader时,从右往左调用
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
use: [{ // use中如需配置其他options 可以使用Object形式, 否则不配置可直接用Array形式,同上css-loader
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "less-loader"
}]
},
]
}
...
}

5引入图片相关loader

在网上随便找2张一大一小图片

npm install --save-dev url-loader

// webpack.config.js
module.exports = {
...
rules: [
...
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
// 当加载图片,小于limit时,会将图片编译成base64字符串形式
// 当加载图片,大于limit时,需要安装file-loader进行加载,加载图片会放入你打包输出的文件目录
limit: 8192 // 8192 / 1024 = xKB
}
}]
}
...
]
...
}

limit属性说明如上方注释,当图片小于limit设定的值时以base64字符串形式插入在打包的js中,此时没问题。

但是,一旦大于设定值,webpack会报错,需要安装file-loader,安装即可,不需要单独配置。

然后wenpack会将引入图片完整打包放入dist文件夹目录下,名称为32位hash值,并将开发环境中引用的图片路径替换为打包生成的图片,而此时index.html引用的为开发目录中(即img文件夹下)的图片,所以打包后再运行index.html发现背景图片不见了

所以这时我们需要当图片大于limit设定值时的打包后页面引入路径更改为dist/xxxxx,好的,进入webpack.config.js,在其中output属性中添加publicPath属性

npm install --save-dev file-loader

// webpack.config.js
module.exports = {
...
output: {
...
// 添加该属性,以后打包文件所有涉及到url的东西,都会自动在路径前添加 dist/
publicPath: 'dist/'
}
...
}

我们通常并不希望,所有的img全部打包在dist文件夹下,而是希望放在dist/img文件夹中,并且希望图片保持原名,但怕重名,还需要加点hash值。

因此,我们可以继续配置url-loader规则

// webpack.config.js
module.exports = {
...
rules: [
...
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192 ,
// 当不希望它打包直接放入dist文件中时,可以添加name属性,
// 当需要保存原名时可以添加[name]
// 当需要防止重名又不需要太长的hash值时可以添加[hash: x] x为你需要hash值位数
name: 'img/[name].[hash:8].[ext]'
}
}]
}
...
]
...
}
因为之前有publicPath配置,所以打包运行index.html页面图片引入路径仍然为dist/img/xxxx.xxx

7ES6转ES5

完成上面一步之后,领导打开他很久没更新的浏览器,发现页面并没有出来,打开控制台一看,全是ES6语法报错,然后立马说:“你这打包不对劲啊,浏览器版本一低就各种报错,我们不能保证用户都使用可以识别ES6语法的浏览器,代码应该要将老旧浏览器都兼容啊。”

好吧,满足他的需求,打开浏览器搜索babel,进入中文官网,点击设置选择Webpack,对照文档在编辑器中一顿输出。

npm install --save-dev babel-loader @babel/core @babel/preset-env

安装完成后,在webpack.config.js中添加规则:

// webpack.config.js
module.exports = {
...
rules: [
...
{
test: /\.js$/,
exclude: /node_modules/, // 排除的目录
// 使用babel-loader将ES6代码转为ES5,做浏览器兼容
// 同时需要建立.babelrc文件,调用@babel/preset-env插件将E6转为E5S
loader: "babel-loader"
}
...
]
...
}

此时,babel-loader已经可以将ES6语法识别,但是打包将ES6转ES5还需要@babel/preset-env插件,所以我们要新建一个名为.babelrc的babel配置文件使用该转译插件:

// .babelrc
{
"presets": ["@babel/preset-env"]
}

9使用Vue

正准备执行回家程序操作,领导叫住说:“项目前端框架要用vue,就用你那玩意搞,正好可以打包。”得,继续搭vue吧。

npm i vue -S

因为vue不仅是在开发环境中使用,并且打包后依然需要依赖vue,所有安装在生成环境中。

安装之后,在main.js中使用一下吧

// main.js
import Vue from "vue";
new Vue({
el: "#app",
data: {
msg: "哈哈,使用了Vue"
}
})
// 然后在index.html中使用一下
// index.html
...
<div id="app">
<h2>{{ msg }}</h2>
</div>
...

好吧,main.js中引入的vue模块,使用的是runtime-only版本的,该版本有vue运行代码,但没有编译template的代码。

那咋办,换个vue模块引入的版本呗,打开webpack.config.js。

// webpack.config.js
module.exports = {
...
// 设置模块如何被解析
resolve: {
// 当安装vue时,默认使用的是runtime-only版本,此版本只含有vue运行的代码,不包含编译template的代码
// 需要重新更换含有runtime-compiler的版本,因为runtime-complier含有complier代码可以用于编译template
// alias(别名): 用别名代替前面的路径,不是省略,而是用别名代替前面的长路径
// 如下,当main.js中import Vue from "vue"时,因为vue是别名,所以实际为import Vue from "vue/dist/vue.esm.js"
// 别名好处是webpack直接会去别名对应的目录去查找模块,减少了webpack自己去按目录查找模块的时间
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
...
}

属性解释如上图,语文好的去官方文档看,反正我是理解不了它说的啥,文档说点白话,通俗易懂不好吗。

简单说alias就是拼接导入模块的路径,emmm,还是举例吧,如下:

// webpack.config.js
...
alias: {
'vue$': 'vue/dist/vue.esm.js' // 这是别名vue
}
... // main.js
import Vue from "vue" <==> import Vue from "vue/dist/vue.esm.js" import Vue from "vue/xxx/xxx" <==> import Vue from "vue/dist/vue.esm.js/xxx/xxx"

好了,应该懂了,反正也是写我自己看的,你们不理解百度去吧。

在我这其实是将alias当成vue模块引入版本重定向,当引入vue,默认引入vue.runtime.common.js文件,而我将引入文件重定向为vue.esm.js。

我怎么知道默认引入哪个版本的?

打开node_modules/vue/package.json,查看其中main属性,就是vue模块默认引入的版本。

其他版本,在node_modules/vue/dist文件夹中。

到这一步,vue配置就完成了。

10vue中template的封装

注意代码的演变

代码抽离1

// main.js
import Vue from "vue";
new Vue({
el: "#app",
template:`<div>{{msg}}</div>`
data: {
msg: "哈哈,使用了Vue"
}
})
// 然后在index.html中使用一下
// index.html
...
<div id="app">
</div>
...

代码抽离二

 main.js
const App = {
template: `<div>{{msg}}</div>`,
data() {
return {
msg: "哈哈,使用了Vue123"
}
}
}
import Vue from "vue";
new Vue({
el: "#app",
template:`<App></App>`,
components: {
App
}
})
// 然后在index.html中使用一下
// index.html
...
<div id="app">
</div>
...

代码抽离三

 main.js
import App from './app.vue'
import Vue from "vue";
new Vue({
el: "#app",
template:`<App></App>`,
components: {
App
}
})
// 然后在index.html中使用一下
// index.html
...
<div id="app">
</div>
...
// app.vue
<template>
<div class='app'>
<div>{{msg}}</div>
</div>
</template>
<script>
export default {
name: 'app',
data() {
return {
msg: "哈哈,使用了Vue1235"
}
},
mounted() { },
watch: {},
computed: {},
methods: {},
components: {}
};
</script>
<style lang='less' scoped='scoped'>
</style>

注意 会遇到两个问题

第一

使用vue文件需要安装vue-loader

cnpm i vue-loader vue-template-compiler -D

第二

vue-loader版本问题

错误是指vue-loader在14版本以上,需要安装另外的插件

方法一:

进入package.json文件中,找到vue-loader的版本

^13.0.0指会自动匹配13.x.x中的最新版本,但是不会匹配到14.0.0

和^(插入符号)一对还有一个符号~(波浪符号)

~13.3.0指会匹配更新到13.3.x的最新版本,但不会更新到13.4.0

然后npm install

方法二:

在webpack.config.js文件中配置以下

const VueLoaderPlugin = require('vue-loader/lib/plugin');

plugins: [
new VueLoaderPlugin()
]

之后就可以使用vue组件 路由 进行基本的开发了

webpack-从零搭建vuecli环境的更多相关文章

  1. 以Aliyun体验机为例,从零搭建LNMPR环境(上)

    使用云服务器搭建 Web 运行环境,尤其是搭建常见的 LNMPR(Linux+Nginx+MySQL+PHP+Redis) 环境,对于开发人员是必备的职场基本技能之一.在这里,借着搭建我的" ...

  2. 以Aliyun体验机为例,从零搭建LNMPR环境(下)

    使用云服务器搭建 Web 运行环境,尤其是搭建常见的 LNMPR(Linux+Nginx+MySQL+PHP+Redis) 环境,对于开发人员是必备的职场基本技能之一.在这里,借着搭建我的" ...

  3. 通过create-react-app从零搭建react环境

    一. 快速开始: 全局安装脚手架: $ npm install -g create-react-app 通过脚手架搭建项目: $ create-react-app <项目名称> 开始项目: ...

  4. 从零搭建 vue-cli 脚手架

    前言: 用了几次 vue-cli 做 vue 项目,感觉没什么大问题,虽然也没有用 vue-router 和 vuex .但是心里一直有个梗,就是最初的目录生成和配置文件,一直没动过,也不知道具体原理 ...

  5. 使用vue+webpack从零搭建项目

    vue到现在已经成为一个热门的框架,在项目实践当中,如果想要创建一个新项目,通常都会使用vue-cli的脚手架工具,毋容置疑能够方便很多,很多东西也不需要自己亲自去配置.都知道,脚手架其实是vue结合 ...

  6. 从零搭建LNMP环境

    Linux就是环境所在的操作系统: Nginx则是一个「高性能的HTTP和反向代理服务器」,官网地址:http://nginx.org/: MySQL则是一个方便地对数据进行增删改查的数据库管理系统, ...

  7. 从零搭建 webpack3 环境 #1 - 安装使用

    目录: (1)什么是webpack (2)webpack核心概念 (3)环境安装 (4)开始使用webpack 1.什么是webpack 官网的一幅图对webpack的解释,从图中可以看出,webpa ...

  8. 从零搭建生产环境的ghost2.0博客

    当前安装过程是在ghost cli 1.9.2上的,由于ghost更新特别快,我安装我个人博客cmlanche.com的时候还是1.9.1,当时没碰到啥问题,到1.9.2就有一点点不一样了,所以要注意 ...

  9. 初探webpack之从零搭建Vue开发环境

    初探webpack之搭建Vue开发环境 平时我们可以用vue-cli很方便地搭建Vue的开发环境,vue-cli确实是个好东西,让我们不需要关心webpack等一些繁杂的配置,然后直接开始写业务代码, ...

随机推荐

  1. 花时三月 终于Spring Boot 微信点餐开源系统! 附源码

    架构 前后端分离:             Nginx与Tomcat的关系在这篇文章,几分钟可以快速了解: https://www.jianshu.com/p/22dcb7ef9172 补充: set ...

  2. 微服务实战系列(六)-网关springcloud zuul

    1. 场景描述 今天接着介绍springcloud,今天介绍下springcloud的路由网关-Zuul,外围系统或者用户通过网关访问服务,网关通过注册中心找到对应提供服务的客户端,网关也需要到注册中 ...

  3. Linux等待队列(Wait Queue)

    1. Linux等待队列概述 Linux内核的等待队列(Wait Queue)是重要的数据结构,与进程调度机制紧密相关联,可以用来同步对系统资源的访问.异步事件通知.跨进程通信等.在Linux中,等待 ...

  4. CSS实现图片圆角显示

    问题描述 在自定义博客园侧边栏公告时,想增加博客头像,但图片默认显示成是方形的,不是很好看,想着改成圆角显示会漂亮些 解决方案 增加css样式 border-radius:25px; 上面的像素值根据 ...

  5. 开源 C#工作流管理平台

    { font-family: 宋体; panose-1: 2 1 6 0 3 1 1 1 1 1 } @font-face { font-family: "Cambria Math" ...

  6. matplotlib绘图教程,设置标签与图例

    大家好,欢迎大家阅读周四数据处理专题,我们继续介绍matplotlib作图工具. 在上一篇文章当中我们介绍了matplotlib这个包当中颜色.标记和线条这三种画图的设置,今天我们同样也介绍三种新的设 ...

  7. 记一次ElementUI源码修改过程

    修改目的 使用ElementUI el-tree过程发现选中节点,键盘移动上下键时(key down\key up)el-tree默认高亮移动的节点,业务上需要重写此事件. ​从官网发现该事件没有暴露 ...

  8. 003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程

    003 01 Android 零基础入门 01 Java基础语法 01 Java初识 03 Java程序的执行流程 Java程序长啥样? 首先编写一个Java程序 记事本编写程序 打开记事本 1.wi ...

  9. 当安装、卸载件包时,出现依赖问题 error: Failed dependencies解决办法

    error: Failed dependencies:-- 依赖关系非常复杂,当你试图先安装任何一个包时都会出现这样的依赖关系错误,这时候你就应该强制安装了,我认为只要你把服务或软件需要的包都装上,强 ...

  10. javaFX 在窗口的标题栏显示当前时间,1秒更新一次时间

    例1:在窗口的标题栏显示当前时间,1秒更新一次时间 1 import java.text.DateFormat; 2 import java.text.SimpleDateFormat; 3 impo ...