欢迎大家来到IT世界,在知识的湖畔探索吧!
学习如何使用Webpack 3和Babel为JavaScript应用程序创建自己的dev、prod和遗留浏览器环境。
获得高级管理人员手册的重要趋势、技巧和战略,以竞争和赢得数字经济。
我注意到一些人仍然在编写JavaScript的古老的ES5语法,这令人沮丧。我想知道是什么阻止他们继续前进。一些人必须受到心理惰性的驱使,但有些人可能只是觉得它太复杂了,无法让他们的新语法在广泛的浏览器中运行。
事实上,现在,我们不必再害怕它了。我们可以设置一个开发环境,在这个环境中,工具决定了代码需要什么转换,以及根据选定的目标(支持的用户代理列表)来加载什么多填充。这些人唯一需要开始“新生活”的是一个合适的设置。
这就是这篇文章的主题。
我的故事
在2012年,我正在寻找一种方法,将我众多的JavaScript模块合并成一个包。我在YUI loader方面有丰富的经验,但是我不想在HTTP 1的时候使用异步加载。它造成了无法忍受的滞后。
我注意到一些项目只是在页眉和页脚之间连接文件。在我的PHP背景下,我看到它更像一个include,或者更确切地说是一个import语句,所以可以控制捆绑。我创建了一个小工具https://github.com/dsheiko/jsic。不久,我发现其中包括了不那么方便,因为他们不关心范围。
然后,我想如果我有一个预编译阶段,为什么不把CommonJS符号(像Node.js)解析成一个bundle文件呢?今年年底,我想出了另一个工具:https://github.com/dsheiko/cjsc。
当发布NPM,寻找合适的措辞描述,我跑进Browserfy…是的,这是我,这不是可以解决的。尽管如此,我多年来一直依赖CJSC,这对我很有帮助。它是快速的,非常简单的设置,并且只专注于一个任务-捆绑CommonJS模块。
然而不久之后,新的解决方案开始出现。我记得,在RollUp中,树摇晃的想法给我留下了深刻的印象。我通常对YAGNI很挑剔,所以感觉就像一个梦。至于Webpack,老实说,我一开始并没有得到它。但是我参与了,而且我认为它现在是一个前端开发人员可用的最好的技术之一。
如果你知道如何处理它,当然…
满足Webpack
Webpack是什么?它是一名bundler——而且是非常聪明的一个。它读取指定的源,如果需要的话,它将被传输。接下来,TypeScript、CoffeeScript等)、解析JavaScript模块(ES模块、CommonJs、AMD)和其他依赖关系(HTML、CSS、SASS、图像等等),并生成一个或多个输出文件。
是的,您可以优雅地将代码库拆分为bundle以获得更好的用户体验。您可以有一个基本的包,代码实现核心用户体验和其他捆绑延迟加载按照他们的优先级。Webpack做的是树的晃动和范围的提升。更重要的是,您可以使用像Uglify这样的插件来处理输出代码。令人印象深刻的,不是吗?让我们举个例子,在实践中看看。
熟能生巧
首先,我们用例子克隆我的样板:
git clone https://github.com/dsheiko/boilerplate/
cd boilerplate/webpack-babel
这个应用程序做的不多。它仅仅显示了几个模块如何静态地解决问题,而另一些模块则通过使用ES动态解析。下一个语法。查看条目脚本:
/webpack-babel/src/index.js
import { utilFoo } from “./util/foo”;
这里我们静态导入foo模块。此代码将包含在主包中。
import { utilBar } from “util/bar”;
我们也使用bar模块,但是这次,我们指定它的位置——不是相对于入口脚本,而是指向基目录,我们将在Webpack配置中设置这个目录。
Promise.all([
import( “./widget/foo” ),
import( “./widget/bar” )
]).then( ([{ widgetFoo }, { widgetBar }]) => {
console.log( “Lazy-loaded modules exports “, widgetFoo(), widgetBar() );
}).catch(( e )=> {
console.error( e );
});
我们还解决了两个动态模块。根据承诺。所有的,当主bundle执行时,它们会同时开始加载。当两个负载时,我们接收它们的导出并将它们转发到控制台。如您所见,我们使用Webpack注释,例如/* webpackChunkName:“foo”*/来指出我们想要的bundle文件的名称。
该示例包含一个现成的清单(package.json)。因此,您可以通过运行获得所有所需的依赖项:
npm i
我们从Webpack想要的是:
-
Transpile ES。我们在JavaScript中使用的下一个语法适用于更广泛的浏览器。
-
从入口脚本中解析所有遇到的(静态和动态)模块。
-
用于生产的小包装。
-
生成两个包:一种是常绿浏览器的薄层,另一种是为传统浏览器提供的
配置Webpack
为了避免代码重复和获得更好的可读性,我们将Webpack配置分成了四个文件:webpack.common.js、webpack.dev.js、webpack.prod。js和webpack.common-legacy.js。第一个是一个抽象的配置,由其他的配置扩展。js将为开发和Webpack.dev.js提供扩展,以进行代码优化。最终,它将被webpack.common legacy.js扩展到传统浏览器所需要的多填充。
让我们从基础开始。
webpack.common.js
module.exports = {
entry: {
index : join( SRC_FULL_PATH, “index.js” )
},
output: {
path: PUBLIC_FULL_PATH,
filename: `[name].js`,
chunkFilename: `[name].v${pkg.version}.widget.js`,
publicPath: PUBLIC_PATH
},
…
在这里,我们指定入口脚本位置并给它一个别名(索引)。接下来,我们设置输出配置。对于主包名,我们使用一个占位符(name),它接收我们已经设置的别名(索引)。对于延迟加载的模块,我们定义一个名称模板和基本公共路径。注意,我将清单版本添加到区块名称中。因此,我们使用项目的每一个新发布版本来破坏CDN缓存。
…
resolve: {
modules: [
“node_modules”,
SRC_FULL_PATH
],
extensions: [ “.js” ]javascript:void(0)
},
…
通过字段解析,我们声明,在解析模块时,Webpack必须尝试搜索相对于相应的NPM包和我们的基本目录(在常量SRC_FULL_PATH中给出)的文件。
plugins: [
new CleanWebpackPlugin([ PUBLIC_PATH ])
]
};
最后,我们调用clean- Webpack -plugin来清理每次Webpack即将在那里编写构建资产时的输出目录。
webpack.dev.js
const merge = require( “webpack-merge” ),
baseConfig = require( “./webpack.common” );
module.exports = merge( baseConfig, {
…
我们通过扩展webpack.common.js来启动我们的dev配置。为此,我们使用webpack-merge。
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: [{
loader: “babel-loader”,
options: {
presets: [ [ “env”, {
“targets”: {
“browsers”: [
“Chrome >= 60”,
“Safari >= 10.1”,
“iOS >= 10.3”,
“Firefox >= 54”,
“Edge >= 15”
]
},
“modules”: false,
“useBuiltIns”: true,
“debug”: false
}] ],
plugins: [
“transform-class-properties”,
“transform-object-rest-spread”,
“babel-plugin-syntax-dynamic-import”,
“transform-runtime”
]
}
}]
}
]
}
我们通过扩展webpack.common.js来启动我们的dev配置。为此,我们使用webpack-merge。
这是关于Babel的配置。在简单的英语中,我们声明Webpack会给每个遇到的人。js模块到Babel loader。Babel将加载env插件预置,这使我们的ES。下面的语法适用于在目标中使用的浏览器匹配模式。浏览器领域。使用useBuiltIns,我们允许Babel在必要时包含多填充。在上面,我们应用以下插件:
-
转换类属性:ES8的解锁类属性。
-
转换-对象-扩展:在对象中解锁破坏。
-
转换运行时:根据env预设配置注入所需的多填充物。
-
Babel -plugin- syndynamicimport:防止Babel在动态模块上出错。
实际上,这已经足够做一个dev构建:
npm run build:dev
对于生产构建,我们在uglifyjs-webpack-plugin中使用管道来缩小捆绑包:
webpack.prod.js
plugins: [
new UglifyJSPlugin()
]
注意,要优化ES。接下来的语法,我们至少需要1.0版的插件:
npm i uglifyjs-webpack-plugin@^1.0.0
至于webpack.prod-legacy。js,我们应用定制化和定制的webpack-合并的对象来覆盖输出和Babel配置。有了这个配置,我们就可以让Webpack输出。/build/legacy,这与默认的不同:./build。我们还扩大了目标浏览器的范围。
现在我们可以生产:
npm run build:prod
首先在Webpack.prod上运行Webpack.js,其次webpack.prod-legacy.js,并产生如下输出:
从日志中可以看到util/foo.js和foo.v0.0.1.widget。js在遗留包中有稍微大一点的大小。这个示例的代码非常少,但是在实际应用程序中,这种差异是非常重要的。
现在,当我们有两组包时,您可能会问,我们将如何根据运行的浏览器来切换它们?这是技巧:
<script type=”module” src=”./build/index.js”></script>
<script nomodule src=”./build/legacy/index.js”></script>
我们在webpack.dev.js中指定的目标浏览器都支持ES模块,因此从script type=模块加载源代码。他们也忽略了脚本的来源。相反,遗留浏览器跳过第一个脚本,从第二个脚本加载。
如果我们启动应用程序,我们将看到控制台。日志输出重定向的HTML(console-log-html | https://github.com/Alorel/console-log-html }模块:
npm start
最后的话
那么,我们取得了什么成果?我们为一个通用的JavaScript应用程序设置了一个dev环境。我们致力于逐步增强,并将应用程序代码拆分为三个包,其中一个表示核心功能并首先加载。当它完成时,它会初始化其他两个包的并发加载。我们使用ES。Next(最新的EcmaScript语法)封装在ES模块中。我们让Webpack与Babel一起编译代码。我们为Webpack构建了三个可运行的配置,用于为开发、生产和遗留浏览器构建。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/37255.html