Skip to content

Commit

Permalink
Snowpack Plugin CDN Import
Browse files Browse the repository at this point in the history
  • Loading branch information
fiuzagr committed Sep 22, 2020
1 parent 7ddc044 commit 2573eef
Show file tree
Hide file tree
Showing 6 changed files with 1,711 additions and 333 deletions.
114 changes: 10 additions & 104 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,104 +1,10 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port
*
.*

!.gitignore
!babel-plugin.js
!index.js
!LICENSE
!package-lock.json
!package.json
!README.md
50 changes: 31 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# snowpack-plugin-import-map
A snowpack plugin that modify your import resource by given map.
# snowpack-plugin-cdn-import

A [Snowpack](https://www.snowpack.dev/) plugin that modify your import resource
to obtain from the CDN.

[Work on modern browsers](https://caniuse.com/mdn-javascript_statements_import).

Based on
[snowpack-plugin-import-maps](https://github.com/zhoukekestar/snowpack-plugin-import-map).

## Quick Start

Step 1: Write your React code as usually like this:
1) Write your code as usually:

```jsx
import React from 'react';
Expand All @@ -13,41 +20,46 @@ ReactDOM.render(
<h1>Hello world!</h1>,
document.getElementById('root'),
);
```

2) Install and configure plugin:

```shell
npm i -D snowpack-plugin-cdn-import
```

Step 2: Modify your snowpack config
Edit `snowpack.config.js`:

```js
module.exports = {
"extends": "@snowpack/app-scripts-react",
"plugins": [
['snowpack-plugin-import-map',
...
plugins: [
...
['snowpack-plugin-cdn-import',
{
dev: true, // if true, import-map transforms imports in development mode too. default: false.
extensions: ['.js', '.jsx','.tsx', '.ts'], // supported extensions. default: ['.js', '.jsx','.tsx', '.ts']
imports: { // map of packages.
react: 'https://cdn.pika.dev/react@^16.13.1',
'react-dom': 'https://cdn.pika.dev/react-dom@^16.13.1',
},
dependencies: require('./package.json').dependencies,
ignore: ['@some/module', /^@another/],
baseUrl: 'https://cdn.skypack.dev', // default value.
extensions: ['.js', '.jsx','.tsx', '.ts'], // default value.
enableInDevMode: false, // default value.
formatImportValue: ({ baseUrl, dependency }) =>
`${baseUrl}/${dependency.name}@${dependency.version}`, // default value.
},
],
],
}
```

Step 3: `npx snowpack build` or `npx snowpack dev`
3) Run `npm run build` or `npm start`

And you will get result like this which can run in browser directly without web-modules deps.
And you will get result like this:

```js
import React from "https://cdn.pika.dev/react@^16.13.1";
import ReactDOM from "https://cdn.pika.dev/react-dom@^16.13.1";
import React from "https://cdn.skypack.dev/react@^16.13.1";
import ReactDOM from "https://cdn.skypack.dev/react-dom@^16.13.1";

ReactDOM.render(
React.createElement("h1", null, "Hello world!"),
document.getElementById('root')
);
```

One more thing, you can deploy it to CDN smoothly ~~~ 🎉
55 changes: 20 additions & 35 deletions babel-plugin.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,34 @@
// Inspired by https://github.com/tbranyen/babel-plugin-resolve-imports-for-browser
// Modified by zhoukekestar @ 20200605

const { types } = require('@babel/core');

let pluginOptions = {}

const visitor = {
const visitor = (imports) => ({
exit(path) {
const { specifiers } = path.node;
const source = path.get('source');

if (!source.node) {
return;
}

// If dep is a thrid lib, convert it to cdn.
if (source.node.value[0] !== '.' && source.node.value[0] !== '/') {

// Map to new resource
if (pluginOptions[source.node.value]) {
const newSource = types.stringLiteral(pluginOptions[source.node.value]);
source.replaceWith(newSource);
}
if (imports[source.node.value]) {
const newSource = types.stringLiteral(imports[source.node.value]);
source.replaceWith(newSource);
}
},
};

// Babel Plugin
module.exports = options => {
pluginOptions = options

return (api, options) => {
api.assertVersion(7);

return {
visitor: {
Program: {
exit(path) {
path.traverse({
ImportDeclaration: visitor,
// ExportDeclaration: visitor,
});
}
});

const babelPlugin = ({ imports }) => (api) => {
api.assertVersion(7);

return {
visitor: {
Program: {
exit(path) {
path.traverse({
ImportDeclaration: visitor(imports),
});
},
},
};
},
};
}
};

module.exports = babelPlugin;
27 changes: 14 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
const { default: traverseAst } = require('@babel/traverse');
const { transformAsync } = require('@babel/core');

const plugin = require('./babel-plugin.js');
const babelPlugin = require('./babel-plugin.js');
const generateImports = require('./generate-imports.js');

// Snowpack Plugin
module.exports = function (snowpackConfig, pluginOptions) {

const extensions = pluginOptions.extensions || ['.js', '.jsx','.tsx', '.ts']; // extensions.
const dev = pluginOptions.dev || false; // for debugging improvements in development.
const imports = pluginOptions.imports || {};
const snowpackPlugin = (_, pluginOptions) => {
const extensions = pluginOptions.extensions || ['.js', '.jsx', '.tsx', '.ts'];
const enableInDevMode = pluginOptions.enableInDevMode || false;
const imports = generateImports(pluginOptions);

return {
async transform(options) {

const { contents, filePath, isDev, fileExt } = options;

if (!(isDev === true && dev === true) &&
extensions.includes(fileExt.toLowerCase())) {
if (
((isDev && enableInDevMode) || !isDev) &&
extensions.includes(fileExt.toLowerCase())
) {
const result = await transformAsync(contents, {
filename: filePath,
plugins: [plugin(imports)],
plugins: [babelPlugin({ imports })],
cwd: process.cwd(),
ast: false,
});
Expand All @@ -28,4 +27,6 @@ module.exports = function (snowpackConfig, pluginOptions) {
return contents;
},
};
};
};

module.exports = snowpackPlugin;
Loading

0 comments on commit 2573eef

Please sign in to comment.