porterhq / porter Goto Github PK
View Code? Open in Web Editor NEW🚛 A middleware for browser module authoring
Home Page: https://porterhq.github.io/porter/zh/
🚛 A middleware for browser module authoring
Home Page: https://porterhq.github.io/porter/zh/
{
"bluebird": {
"2.3.11": {
"main": "./js/main/bluebird.js"
}
},
"ez-editor": {
"0.2.4": {
"dependencies": {
"crox": "1.3.1",
"extend-object": "1.0.0",
"heredoc": "1.3.1",
"inherits": "2.0.1",
"jquery": "1.11.3",
"yen": "1.2.4"
}
}
},
"heredoc": {
"1.2.0": {},
"1.3.1": {}
},
"yen": {
"1.2.4": {}
}
}
The idea is to flat all module versions into a two level object. Detailed descriptions like main
and dependencies
are all put under the two level path, such as alias.heredoc['1.2.0']
.
att
两种使用场景:
后者比较容易达成一致,直接 require('./some.css') 就可以了。是否支持 https://github.com/css-modules/css-modules 再议。
前者是本文讨论重点,目前比较纠结的地方有:
针对入口代码,有两种方式:
!= linkTag('/app.css')
link(rel='stylesheet', href='/app.css')
这里假设 app.css 代码如下:
/*
*= require('./base')
*= require('./iconfont')
*= require('./layout')
*/
/* styles */
前者效仿 Rails 里的 Sprockets,在开发模式下实际渲染的时候,会展开为:
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="iconfont.css">
<link rel="stylesheet" href="layout.css">
<link rel="stylesheet" href="app.css">
在上线前,则通过 rake assets:precompile
任务来压缩、合并样式文件,从而兼得开发时的便利和上线时的性能优化。
后者,link(rel='stylesheet', href='/app.css')
这种用法,则等同于直接写 <link>
标签,由 Oceanify 在响应 app.css 请求的时候提供合并好的 app.css
不过,也不是必须这么做,如果我们采用 @import
作为引用依赖的方式,那么在开发时,我们就可以不合并样式,靠原生的 @import
即可。也就是说 app.css 可以写成这样:
@import './base.css'
@import './iconfont.css'
@import './layout.css'
/* styles */
在上线合并的时候,交给 oceanify.compileAll()
处理掉这些 @imports
。
所以大家不妨投票,选择入口代码写法:
!= linkTag
<link>
直接写以及模块声明方式:
/*= require('./base') */
@import './base.css'
我倾向选择 2, 2
id => seq
Safari has it now WebKit/WebKit@6c1996a , Chrome and Edge has it for a while already, the default bundling behavior should be upgraded a bit to better utilize browser capability.
about import.meta.resolve(), currently porter only handles import.meta.url and import.meta.glob() (non-standard), the transformation of it should be refactored to handle following usages:
import.meta.resolve() looks like the require.resolve() supported by porter though.
Possible changes:
document
and window
shall not be referenced.importScripts()
.Syntaxes practiced by Webpack's worker-loader currently:
import Worker from 'worker-loader!./Worker.js';
const worker = new Worker();
Or with module rules configured:
import Worker from './file.worker.js'
const worker = new Worker();
As a matter of fact, this is no different than create worker with vanilla Web Worker syntax:
const worker = new Worker('file.worker.js')
// or if file.worker.js is a ES6 module or CommonJS module that requires Porter to intervene
const worker = new Worker('file.worker.js?main')
With ?main
appended, while serving file.worker.js
:
importScripts()
Regarding the syntax introduced by worker-loader,
require('worker-loader!./Worker.js')
// is actually translated into
function WorkerLoader(dep) { // dep => './Worker.js'
const uri = require.resolve(dep)
return new Worker(uri)
}
Whether or not the options of worker-loader shall be supported is still under consideration.
In a typical web application development, one might want to refactor some of the components as modules to better sharing them between apps. In rare cases, the refactored modules want to require some component of the app. Whether or not this is anti-pattern is not the issue I want to discuss about here. This issue only talks about the changes needed to allow this kind of usage.
For example, components may require('@app/common')
, @app/common
may require util
of the comonents:
app
├── components
│ └── util
└── node_modules
└── @app
└── common
https://github.com/Hacker0x01/react-datepicker
The bug is an obvious one. react-datepicker has its main set to lib
in package.json, which should be parsed as the alias of lib/index.js
.
Currently all three paths can access home.js
:
/porter-app/1.0.0/home.js
/porter-app/home.js
/home.js
However, /porter-app/home.js
shouldn't be available since it causes chaos in following scenario:
// home.js
require('../foo')
When loader resolves ../foo
above, the context is porter-app/1.0.0/home
. The resolved module id will be porter-app/foo
, which is accessible in development (because porter middleware handles that), but not available in production due to there's no ../foo
actually.
I think the middleware should only allow two types of paths:
/porter-app/1.0.0/home.js
/home.js
The latter one is for main scripts, <script src="/home.js"></script>
is much easier to write. After home.js
loads, and the loader kicks in, all components and modules loaded later will have their versions specified.
rt
In single page applications, there's few entries components. Conventionally, engineers wants to bundle everything into one script to optimize the network performance. In ad industry, the situation is quite similar since the html banner is a (poor man's) single page application. In cases like these, we can use oceanify.compileComponent(id, { includeModules: true })
to bundle them all.
Currently this functionality has been used in our products for a long time, but the test cases in this repo has yet to cover. This issue serves as a reminder.
Theoretically we can generate seajs alias based on module usages in components and themselves.
Currently this is possible,
// in component code
require('https://a1.alicdn.com/assets/qrcode.js')
But this is not covered in tests yet, needs work. Also, currently there can be no return values since the id
passed to require
is the full uri but modules are all registered by id in oceanify.registry
.
Currently the compileAll
processes following stuff,
main
and bundle by module.Recently we've been trying react (a bit old-fashioned, i know), which fancy requiring lib modules by full id such as fbjs/lib/warning.js
. [email protected] manages to support this, but the implementation is quite limited yet.
If this behavior is the favored one, we might need to add a tree scanning logic and do all the node_modules by actual entries other than the main
in package.json.
For module source like this:
// bar.js
var foo = require('foo')
// some comment
Currently it will be wrapped as:
define('bar', ['foo'], function(require, exports, module) {// bar.js
var foo = require('foo')
// some comment })
Reported by @chenhui5416
https://a1.alicdn.com/kb/3.9.89/assets/style/app.css?t=1637146386905 starting to bloat
Normally, macOS formats the disk with a case insensitive file system, which makes components' resolutions a bit wild since both require('fooBar')
and require('foobar')
work. But when the file is compiled and deployed onto a Linux box, the default file system is case sensitive, which makes either require('fooBar')
or require('foobar')
fail.
😕
👻
For better coverage of module formats.
Porter is drastically refactored to make following enhancements and new features be possible:
${name}/${version}/~bundle.js
) on packages that have multiple entries, such as lodash and fbjs.require("worker-loader!foo)
to migrate existing code.require.resolve
to new Worker(require.resolve('foo'))
, which is basically the same as above.browser
field #1https://github.com/erzu/oceanify/blob/master/lib/parseAlias.js#L49
http://bower.io/docs/creating-packages/#main
bower 的main 可以是Array, 处理时没有考虑到,导致 path.join 的参数中的main是一个array,而导致报错。
https://github.com/erzu/oceanify/blob/master/lib/parseAlias.js#L56
require('./中文.js'); // works
require('./\u4E2D\u6587.js'); // does not work
the latter form generates requests like /\u4E2D\u6587.js
currently, which needs to be converted back to 中文.js
before resolving it.
Since 5.1.0-beta, oceanify has introduced module transformation with babel. To some webpack users, use case like below might be familiar:
if (process.env.BROWSER) {
require('./browser')
} else {
require('./node')
}
Currently oceanify has not support this however. In Oceanify both ./browser
and ./node
will be parsed as module dependencies which will eventually fail when loaded in the browser. To fix this, we can add an extra transformation with babel, with process.env.BROWSER positive, and drop the dead branch.
There's a babel plugin already. I'll see to it whenever possible.
we've got partial less support now, but css modules aren't ready yet.
Currently, loose-envify is applied specifically already. Let's see if a once and for all solution is possible.
heredoc is a module that supports both browser and node. In its repo, both the source code of the module and the test cases are shared between these two environments.
In node, we can of course require('../index')
in test/
folder to grab the heredoc module. In browser however, with current possible scenario setup by oceanify@4, we cannot require a module that is out of the test/
folder. In the other hand, we must require('heredoc')
.
This makes code sharing a little fuzzy.
Here's one possible fix. We can add a opts.self
option to indicate that the source of current module (all the .js
files within current working directory) shall be available. Then with opts.self
turned on, if any module within components
require some dependencies beyond components
' scope, we'll change it to the mapped require.
Take the heredoc example. require('../index')
will be checked to see if path.resolve(cwd, 'test', '../index') + .js
exists or not. If positive, the require statement shall be changed to require('heredoc/index')
, then the oceanify middleware can take over the rest.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.