日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

nej+regular环境使用es6的低成本方案

發布時間:2025/3/19 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nej+regular环境使用es6的低成本方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文來自?網易云社區?。

?

希望在生產環境中使用es6/7,babel應該是最普遍的選擇。這是babel官網中,它對自己的定義:

Babel 自帶了一組 ES2015 語法轉化器。這些轉化器能讓你現在就使用最新的 JavaScript 語法,而不用等待瀏覽器提供支持。

babel就像一個javascript文件預處理器,你可以自由使用es6/7語法,不用當心兼容性問題,因為瀏覽器中運行是babel為你處理妥帖的代碼。為了方便使用,它提供了許多使用方法:webpack、gulp、browserify、grunt......

通過哪種方式來在當前技術棧(nej+regular+stateman)中使用babel,是一個值得深思熟慮問題,而沒有經過深思熟慮就試圖使用webpack的我,一度掉進了一個坑中:

?

webpack + babel 的踩坑過程

webpack應該是目前最流行的構建工具,關于它和babel的使用方法,網上的資料汗牛充棟,前人對各種可能發生的問題(比如ie8的兼容)基本都有了解決方法,換句話說就是這條路的坑比較少。

但是對我們而言,webpack+babel的方式存在以下幾個問題:

  • 改變打包方式帶來的不確定性。貿然在生產環境中替換打包工具,風險太大。
  • 大量的歷史代碼中使用的nej改良后的amd語法,webpack無法識別。webpack支持amd語法,也支持路徑別名,但僅限于以別名開頭的路徑
  • //webpack.config.js ... alias: {pro: 'a/b/c' } ...//test.js define(['pro/d']) //define(['a/b/c/d']) define(['pro/e/{mode}/f']) //error

    這個問題可以通過編寫babel插件,根據nej的模塊語法定制修改:babel-plugin-transform-nej-module

  • ftl注入,多入口。這兩個問題可以從考拉的一篇文章中找到答案。
  • 除此之外,還遇到一個比較特殊的問題,webpack無法識別我們歷史代碼中的一個文件。

    綜上所述,如果有著豐富的webpack使用經驗,能夠承受改變打包方式帶來的風險,可以考慮使用webpack來引入babel。

    從webpack的踩坑過程中,找到了做es6/7改造的兩個原則:

  • 不改變歷史代碼
  • 不改變打包方式
  • ?

    gulp + babel

    根據上述的兩個原則,,gulp無疑是個很好的選擇:

  • 當檢測到文件是用nej的語法引入模塊時,不處理; //不改變歷史代碼
  • 當檢測到文件是用es6語法引入模塊時,把它改造成nej的語法,再進行es6/7的語法轉換; // 保證nej可以識別,打包方式不變
  • 因此,利用gulp來引入es6/7,過程應該是這樣的:

    虛線方框里是需要我們來做的工作:

  • import/export轉化為nej的模塊語法
  • 根據兼容需求,轉化es6/7語法
  • 通過babel的插件可以完成這兩個任務:

    ?

    import/export轉化為nej的模塊語法

    babel本身會將import和export的語法轉化為commonjs格式:

    轉化前轉化后目標
    import a from 'A'var a = require('A')define('A', function(a){...}
    export {b}exports.b = b;{... return b}

    這個轉化只是個簡寫,詳細的轉化后代碼可以在這里看,代碼解析可以參考這篇文章

    目前沒有前人的工作可以直接實現的我們的目標,所以必須自己編寫一個,babel插件的編寫可以參考這篇文章。簡單的說,babel會把javascript代碼解析為一棵語法樹,通過修改這棵樹來方便、準確的修改javascript代碼。

    插件babel-plugin-transform-es2015-modules-nej將es6的模塊語法轉換為nej的模塊語法,主要流程為:

    判斷是否為nej模塊->解析import,生成路徑數組、文件名數組->解析export,生成return語句->將除了import和export的其它代碼生成內容數組,并將return語句放入->利用這三個數組構建amd格式的模塊語法

    ?

    根據兼容需求,轉化es6/7語法

    babel通過.baberc來配置

    //.babelrc {preset: '...',plugins: '...' }

    可以看到,babel的配置由preset和plugins構成,preset是插件的集合,選擇預設的插件集合配合一些解決比較特殊問題的插件,來完成babel的配置。

    在npm中搜索babel-preset和babel-plugin能夠獲得3000+的結果,在預設的插件集合中,babel-preset-env是非常省心的選擇,它是一個動態的插件集合,通過指定你想要兼容的瀏覽器,它會幫你引入需要的插件。加上上一步中編寫的transform-es2015-modules-nej,配置就完成了。

    babel轉化后的代碼會默認使用嚴格模式,如果歷史代碼中存在嚴格模式下報錯的問題,記得在插件中加上transform-remove-strict-mode

    {"presets": [["env", {"targets": {"browsers": ["last 2 versions", "IE 8-10"]}}]],"plugins": ["transform-es2015-modules-nej"] }

    API的轉化

    最后一個問題是:babel只轉換語法,不轉換api,所以需要polyfill來保證generate、async這些喜聞樂見的api的正常使用。polyfill.min.js文件體積不算小:102kb,需要在每個頁面中都引用,當然,加載一次過后,緩存可以幫助節省大部分時間。

    最優解是在打包的時候,根據每個頁面使用的api來引入對應的polyfill。babel的官方插件babel-plugin-transform-runtime,能做到只引入文件用到的api的polyfill,但是它的引入方式為commonjs。實際上,即使是amd方式,也難以和nej的模塊語法完美融合。而且,針對文件來引用polyfill仍然使得同一個頁面引用多個相同polyfill,加載重復數據。

    因此,對于API的轉化,由如下三種解決方案

    • 每個頁面引入polyfill.min.js;
    • 每個文件引入對應polyfill;(修改插件babel-plugin-transform-runtime)
    • 打包時引入頁面所需polyfill;(利用打包來polyfill)

    ??

    最終方案

    graph TDA(gulp)-->|監視|B[raw/xxx/a.js]B-->|發生改變|C(babel)C-->|babel.rc|D(src/xxx/a.js)A-->|sourcemap|E(src/xxx/a.js.map)

    gulp檢測文件的變動,通過babel轉化es6代碼,轉化過程中,gulp生成對應文件的sourcemap:a.js.map。

    分為四步:

  • 配置gulp
  • 配置babelrc
  • 配置gulp+babel生成sourcemap
  • 引入polyfill
  • ?

    1. 配置gulp

    安裝gulp和babel

    npm install --save-dev gulp; npm install --save-dev gulp-babel

    配置gulpfile.js:

    const gulp = require('gulp'); const babel = require('gulp-babel');gulp.task('babel', () =>gulp.src('./raw/**/*.js').pipe(babel()).pipe(gulp.dest('./src')) );gulp.task('watch:babel', () => {gulp.watch('./raw/**/*.js', ['babel']); });

    2.配置babelrc

    {"presets": [["env", {"targets": {"browsers": ["last 2 versions", "IE 8-10"]}}]],"plugins": ["transform-remove-strict-mode","transform-es2015-modules-nej"] }

    提醒不熟悉babel的小伙伴一句,這些插件和預設需要安裝,babel包中并不提供:

    npm install --save-dev babel-preset-env; npm install --save-dev babel-plugin-transform-remove-strict-mode; npm install --save-dev babel-plugin-transform-es2015-modules-nej;

    3.配置gulp+babel生成sourcemap

    修改gulpfile.js如下:

    const gulp = require('gulp'); const babel = require('gulp-babel'); const sourcemaps = require('gulp-sourcemaps');gulp.task('babel', () =>gulp.src('./raw/**/*.js').pipe(sourcemaps.init()).pipe(babel()).pipe(sourcemaps.write('.',{sourceRoot: 'raw'})).pipe(gulp.dest('./src')) );gulp.task('watch:babel', () => {gulp.watch('./raw/**/*.js', ['babel']); });

    生成sourcemap后,可以在瀏覽器中運行轉換后代碼,調試轉換前代碼。

    4. polyfill

    <script src="/res/vendorjs/core/polyfill.min.js"></script>

    總結及效果

    目前測試的情況,ie9及其以上環境有效,理論上支持ie8。

    es6最大的優點是給碼農帶來的快樂,一個不是很明顯的快樂對比如下:

    原來這樣寫:

    NEJ.define(['text!./app.html','pro/cache/indexCache','pro/util/userUtil','pro/module/module','pro/util/util' ],function(template,IndexCache,userUtil,Module,util){var App = Module.extend({template: template,config: function(){this.supr();this.cache =new IndexCache();util.extend(this.data, {columns: [],columnConfig: [{isShowIntroPic: false,isVertical: false},{isShowIntroPic: true,isVertical: true},{isShowIntroPic: true,isVertical: true},{isShowIntroPic: false,isVertical: false}],courseUrlPrefix: userUtil.isUserLogin() ? this.$urlPrefix.termDetailPrefix : this.$urlPrefix.courseDetailPrefix});this.data.courseUrl = "/path/courses/";},init: function(){this.supr();this.getInitData();},enter: function(){this.supr();},getInitData: function() {this.cache.courseColumn( this.onGetCourseColumn._$bind(this));},onGetCourseColumn: function(data) {for(var i=0; i<data.length; i++ ) {var columnData = data[i];var columnConfig = this.data.columnConfig[i];var column = {title: columnData.sectionName,isShowIntroPic: columnConfig.isShowIntroPic,isVertical: columnConfig.isVertical,introPicSrc: columnData.photoUrl,courseCards: []};var coursesData = columnData.termCardVos;for(var j=0; j<coursesData.length; j++) {var courseData = coursesData[j];column.courseCards.push({title: courseData.courseName,url: this.data.courseUrlPrefix.replace(':termid', courseData.termId),src: courseData.bigPhoto,price: courseData.price == 0 ? '免費' : courseData.price + '元'})}this.data.columns.push(column);}this.$update();},leave: function(){this.supr();}});return App; });

    現在可以這樣寫:

    import template from './app.html'; import IndexCache from 'pro/cache/indexCache'; import userUtil from 'pro/util/userUtil'; import Module from 'pro/module/module'; import util from 'pro/util/util';const App = Module.extend({template: template, config: function () {this.supr();this.cache = new IndexCache();Object.assign(this.data, {columns: [],columnConfig: [{isShowIntroPic: false,isVertical: false}, {isShowIntroPic: true,isVertical: true}, {isShowIntroPic: true,isVertical: true}, {isShowIntroPic: false,isVertical: false}],courseUrlPrefix: userUtil.isUserLogin() ? this.$urlPrefix.termDetailPrefix : this.$urlPrefix.courseDetailPrefix});this.data.courseUrl = '/path/courses/';},init: function () {this.supr();this.getInitData(); },enter: function () {this.supr();},getInitData: async function () {const data = await this.cache.courseColumn();for(let [columnIdx, columnData] of data.entries()) {let columnConfig = this.data.columnConfig[columnIdx],column = {title: columnData.sectionName,isShowIntroPic: columnConfig.isShowIntroPic,isVertical: columnConfig.isVertical,introPicSrc: columnData.photoUrl,courseCards: []},coursesData = columnData.termCardVos;for(let courseData of coursesData) {column.courseCards.push({title: courseData.courseName,url: this.data.courseUrlPrefix.replace(':termid', courseData.termId),src: courseData.bigPhoto,price: courseData.price == 0 ? '免費' : `${courseData.price}元`});}this.data.columns.push(column);}this.$update();},leave: function () {this.supr();} });export {App };

    本文來自網易云社區,經作者曹陽授權發布。

    原文地址:nej+regular環境使用es6的低成本方案

    更多網易研發、產品、運營經驗分享請訪問網易云社區。

    總結

    以上是生活随笔為你收集整理的nej+regular环境使用es6的低成本方案的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。