导航:首页 > 源码编译 > 前端分模块编译

前端分模块编译

发布时间:2024-04-05 12:02:11

Ⅰ 如何理解前端模块化

前端模块化
javaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀

这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(mole)了,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码

模块
既然JavaScript不能handle如此大规模的代码,我们可以借鉴一下其它语言是怎么处理大规模程序设计的,在Java中有一个重要带概念——package,逻辑上相关的代码组织到同一个包内,包内是一个相对独立的王国,不用担心命名冲突什么的,那么外部如果使用呢?直接import对应的package即可

import java.util.ArrayList;
遗憾的是JavaScript在设计时定位原因,没有提供类似的功能,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。

一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。模块开发需要遵循一定的规范,各行其是就都乱套了

规范形成的过程是痛苦的,前端的先驱在刀耕火种、茹毛饮血的阶段开始,发展到现在初具规模,简单了解一下这段不凡的历程

函数封装
我们在讲函数的时候提到,函数一个功能就是实现特定逻辑的一组语句打包,而且JavaScript的作用域就是基于函数的,所以把函数作为模块化的第一步是很自然的事情,在一个文件里面编写几个相关函数就是最开始的模块了

function fn1(){
statement
}

function fn2(){
statement
}
这样在需要的以后夹在函数所在文件,调用函数就可以了

这种做法的缺点很明显:污染了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间没什么关系。

对象
为了解决上面问题,对象的写法应运而生,可以把所有的模块成员封装在一个对象中

var myMole = {
var1: 1,

var2: 2,

fn1: function(){

},

fn2: function(){

}
}
这样我们在希望调用模块的时候引用对应文件,然后

myMole.fn2();
这样避免了变量污染,只要保证模块名唯一即可,同时同一模块内的成员也有了关系

看似不错的解决方案,但是也有缺陷,外部可以随意修改内部成员

myModel.var1 = 100;
这样就会产生意外的安全问题

立即执行函数
可以通过立即执行函数,来达到隐藏细节的目的

var myMole = (function(){
var var1 = 1;
var var2 = 2;

function fn1(){

}

function fn2(){

}

return {
fn1: fn1,
fn2: fn2
};
})();
这样在模块外部无法修改我们没有暴露出来的变量、函数

上述做法就是我们模块化的基础,目前,通行的JavaScript模块规范主要有两种:CommonJS和AMD

CommonJS
我们先从CommonJS谈起,因为在网页端没有模块化编程只是页面JavaScript逻辑复杂,但也可以工作下去,在服务器端却一定要有模块,所以虽然JavaScript在web端发展这么多年,第一个流行的模块化规范却由服务器端的JavaScript应用带来,CommonJS规范是由NodeJS发扬光大,这标志着JavaScript模块化编程正式登上舞台。

定义模块
根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性

模块输出:
模块只有一个出口,mole.exports对象,我们需要把模块希望输出的内容放入该对象

加载模块:
加载模块使用require方法,该方法读取一个文件并执行,返回文件内部的mole.exports对象

Ⅱ Web前端开发主要学哪些课程

老实说,前端经过这几年的快速发展,网上的文章和教程还是蛮多的,有经验的人能够根据资料制定出属于自己的学习方法和路径,但对于小白来说,还是有些难度。知了姐来给大家分享前端学习路径。针对0基础,非科班,没有编程经验,想学前端,但是不知道如何入门的人群。

基础部分:

1、HTML + CSS 这部分学习,可以模仿一些网站做些页面,在实践中积累经验。做到能与UI对接,能100%重构网站静态页面的开发,为后期编写页面逻辑、动态效果打基础。

2、Javascript 要学的内容实在很多,如果没有其他编程语言的基础的话,学起来可能要费些力,这个阶段需要掌握编程基础概念,培养逻辑思维能力。能够独立完成网站的页面开发(包括合理布局,JavaScript操作DOM)

编译前端和后端各有什么特点,各自包含编译过程的哪几个部分

编译前端主要包括词法分析、语法分析、语义分析、中间代码生成这几个部分,后端则包含代码优化和目标代码生成部分。前端的特点是仅与编译的源语言有关,而后端则仅与编译的目标语言及运行环境有关。

将编译过程划分成前端和后端,主要目的是在多种源语言和多种目标语言的开发过程中,可以灵活搭配组合,消除重复开发的工作量,提高编译系统的开发效率。

Ⅳ 编译程序分为哪几个主要部分

1、词法分析

词法分析的任务是对由字符组成的单词进行处理,从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号,把作为字符串的源程序改造成为单词符号串的中间程序。执行词法分析的程序称为词法分析程序或扫描器。

2、语法分析

编译程序的语法分析器以单词符号作为输入,分析单词符号串是否形成符合语法规则的语法单位,如表达式、赋值、循环等,最后看是否构成一个符合要求的程序,按该语言使用的语法规则分析检查每条语句是否有正确的逻辑结构,程序是最终的一个语法单位。

3、中间代码生成

中间代码是源程序的一种内部表示,或称中间语言。中间代码的作用是可使编译程序的结构在逻辑上更为简单明确,特别是可使目标代码的优化比较容易实现。中间代码即为中间语言程序,中间语言的复杂性介于源程序语言和机器语言之间。

4、代码优化

代码优化是指对程序进行多种等价变换,使得从变换后的程序出发,能生成更有效的目标代码。所谓等价,是指不改变程序的运行结果。所谓有效,主要指目标代码运行时间较短,以及占用的存储空间较小。这种变换称为优化。

5、目标代码生成

目标代码生成是编译的最后一个阶段。目标代码生成器把语法分析后或优化后的中间代码变换成目标代码。



(4)前端分模块编译扩展阅读:

特点

数据结构分析和综合时所用的主要数据结构,包括符号表、常数表和中间语言程序。符号表由源程序中所用的标识符连同它们的属性组成。

其中属性包括种类(如变量、数组、结构、函数、过程等)、类型(如整型、实型、字符串、复型、标号等),以及目标程序所需的其他信息。常数表由源程序中用的常数组成,其中包括常数的机内表示,以及分配给它们的目标程序地址。

分析部分源程序的分析是经过词法分析、语法分析和语义分析三个步骤实现的。词法分析由词法分析程序(又称为扫描程序)完成。

其任务是识别单词(即标识符、常数、保留字,以及各种运算符、标点符号等)、造符号表和常数表,以及将源程序换码为编译程序易于分析和加工的内部形式。


Ⅳ 如何使用 ES6 编写一个 React 模块,并且编译后发布到 NPM

如果你在使用 React, 那么肯定已经撸了好多自己的组件, 并尝试着共享出来。在 OneAPM 前端开发过程中, 我们也曾遇到了一些组件共享的问题:
例如:
是通过 git 直接发布还是通过 NPM 发布 ?
发布的是 ES5 的代码还是 ES6 的代码 ?
如何解决 Babel5 和 Babel6 的冲突 ?
这篇文章会通过编写一个叫做 MyComponet 的例子来演示发布一个模块需要注意的地方, 并不涉及单元测试和代码规范等。
前端开发果真是发展迅猛,刚享受到由模块化,组件化和单元测试带来的种种好处,又得迅速拥抱 Grunt, Gulp, Browserify, Webpack 这类自动化工具的变革。除了工具和生态圈,JavaScript 本身也在飞速发展着。ES2015(ES6) ,ES2016(ES7) ... 照这样的节奏,几乎是一年一个标准。标准多了,为解决兼容性的问题,竟也派生出了 源代码 和 编译 的概念。前端开发者通过语法糖、转化器、Polyfill 等,可以享受到标准乃至尚未定稿草案里的规范的便利,大幅提升开发效率。
至于这个模块本身,它的功能特别简单, 就是显示模块自身的的属性。
源代码
我们来编写组件 MyComponent.jsx ,放到项目的 src 目录下。

import React from 'react';

const MyComponent = props=> {
return <div>
props:
<pre>{JSON.stringify(props, null, 2)}</pre>
</div>
}

export default MyComponent;

关于各种文件放在哪里, 这里是我推荐的一些约定:
src 下用于存放源代码
lib 是编译后的代码,这个目录只读
所有包含 ES6 语法的文件名统一后缀为 .es6
所有包含 JSX 语法的文件后统一缀名为 .jsx
假设源代码里还有另外两个文件 foo.es6 和 bar.js,简化起见都丢到 src 的根目录下。
编译
为了把 ES6 代码编译成 ES5,需要安装 Babel,这个工具可以说野心极大,一次编译可以让 JavaScript 运行在所有地方。(听起来是不是有点 Java 的作风)
目前最常用的是 Babel5 版本,但是 Babel6 版本的设计更为精巧,已经非常推荐更新。也正是由于 Babel 有两个版本,所以开发过程中很有可能遇到这样的情况,
模块 A 的开发依赖于 Babel5 版本,而模块 B 依赖于 Babel6 版本。
解决这个问题最好的做法就是把 A 和 B 拆开,独立开发和发布。并且在发布到 NPM 的时候发布是的编译后的,也就是 ES5 版本的代码。
所以如果你的机器上的 babel 是全局安装的,是时候卸载它了,因为它的版本不是 5 就是 6 ,会导致一些不可预见的问题。
npm uninstall babel-cli --global
正确的安装方式是把 babel-cli 作为 develeopment 的依赖
npm install babel-cli --save-dev
使用的时候并不是直接调用全局的 Babel 而是调用依赖里的 Babel 可执行文件
./node_moles/.bin/babel
如果按照前文的约定来组织代码,src 目录结构看起来是这样的

src
├── bar.js
├── foo.es6
└── MyComponent.jsx

模块所有的代码都在一个目录下,这样编译过程就简单多了,两条命令就可以完成
./node_moles/.bin/rimraf lib
./node_moles/.bin/babel src ---files --source-maps --extensions .es6,.es,.jsx --out-dir lib
输出目录的结构

lib
├── bar.js
├── foo.js
├── foo.js.map
├── MyComponent.js
└── MyComponent.js.map

具体解释一下各个命令的作用:
第一条命令 ./node_moles/.bin/rimraf lib
作用 编译前清空之前的 lib 目录,这是一个好习惯,可以杜绝对 lib 下的文件的任何手动更改。
第二条命令
./node_moles/.bin/babel src --out-dir lib --source-maps --extensions .es6,.es,.jsx ---files
作用 遍历 src 目录下的文件,如果后缀名是 .es/.es6/.jsx 中的一种,就编译成 ES5,否则就直接拷贝到输出目录 lib 下
参数详解:
--out-dir lib 指定输出目录为 lib
--extensions .es6,.es,.jsx 指定需要编译的文件类型
---files 对于不需要编译的文件直接拷贝
--source-maps 生成 souce-map 文件
编译过程中还隐含了一个步骤就是加载 .babelrc 文件里的配置,该文件内容如下

{
"presets": [
"es2015",
"stage-0",
"react"
]
}

这是因为 Babel6 采用了插件化的设计,做到了灵活配置:如果要转换 JSX 语法文件,就加上 react 的 preset,同时项目依赖里要添加
babel-preset-react

npm install babel-preset-react --save-dev

样例代码
开发和调试 React 模块目前最好用的打包工具还是 Webpack,在项目跟目录下,新建一个 example 目录:
example/index.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body></body>
<script src="bundle.js"></script>
</html>

example/src/index.jsx

import React from 'react';
import MyComponent,{foo,bar} from '../../';
import {render} from 'react-dom';

var element = document.createElement("div");
document.body.appendChild(element);
render(<MyComponent name="myComponent"/>, element);

webpack.config.js

var path = require('path');

mole.exports = {
entry: path.join(__dirname, 'example', 'src', 'index.jsx'),
output: {
filename: 'bundle.js'
},
mole: {
loaders: [{
test: /\.jsx$/,
loader: 'babel',
include: [
path.join(__dirname, 'example')
]
}]
},
devServer: {
contentBase: path.join(__dirname, 'example')
}
}

运行样例代码

./node_moles/.bin/webpack-dev-server

发布
发布前,还有一件事就是为你的模块添加一个入口文件 index.js

mole.exports = require('./lib/MyComponent');
exports.default = require('./lib/MyComponent');
exports.bar = require('./lib/bar');
exports.foo = require('./lib/foo');

接下来就是发布到 NPM 了。

npm publish

使用
别的开发者在使用你新发布的模块的时候可以这样导入

import MyComponent,{foo,bat} from 'react-component-example'

导入的直接是 ES5 代码,跳过编译从而避免了出现 Babel 版本不一致的问题,并且速度更快,是不是很棒!
不过假设你的模块包含很多组件,开发者可能只想用其中的一个或某几个,这时可以这样导入:

import MyComponent from 'react-component-example/src/MyComponent.jsx'

导入的是 ES6 代码,并且会被加入父级项目的编译过程。

阅读全文

与前端分模块编译相关的资料

热点内容
易语言递归算法 浏览:284
中国有出什么加密币吗 浏览:530
加密程序不小心删除 浏览:415
清除空文件夹的代码 浏览:608
相册视频水印怎么去掉的app 浏览:616
鸡啄米c编程入门 浏览:826
iphone手机视频如何加密或隐藏 浏览:289
车床一个轴的编程 浏览:6
任何APP都借不了款怎么办 浏览:362
linux刷新命令 浏览:518
解压配音的小视频 浏览:652
phptable页 浏览:813
人工智能怎么摆脱算法 浏览:72
思科显示配置命令 浏览:411
网上为什么对程序员这么多评论 浏览:84
app续费怎么算 浏览:775
安卓手机怎么把相册传到苹果 浏览:261
高中信息技术算法教案 浏览:245
百战程序员职业 浏览:606
abb机器人焊接操作编程教学视频 浏览:384