mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-26 23:52:06 +00:00
web worker example
This commit is contained in:
parent
56bcd609fd
commit
cd9a6c2c05
21
examples/web-worker/.eslintrc.js
Normal file
21
examples/web-worker/.eslintrc.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint'
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||||
|
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||||
|
'plugin:vue/strongly-recommended'
|
||||||
|
],
|
||||||
|
// required to lint *.vue files
|
||||||
|
plugins: [
|
||||||
|
'vue'
|
||||||
|
],
|
||||||
|
// add your custom rules here
|
||||||
|
rules: {}
|
||||||
|
}
|
11
examples/web-worker/.gitignore
vendored
Normal file
11
examples/web-worker/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# logs
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# Nuxt build
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Nuxt generate
|
||||||
|
dist
|
26
examples/web-worker/README.md
Normal file
26
examples/web-worker/README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# web-worker
|
||||||
|
|
||||||
|
> Nuxt.js project
|
||||||
|
|
||||||
|
In nuxt 1.4 and below you have to create a production build to use web workers.
|
||||||
|
|
||||||
|
## Build Setup
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
# install dependencies
|
||||||
|
$ npm install # Or yarn install
|
||||||
|
|
||||||
|
# serve with hot reload at localhost:3000
|
||||||
|
# nuxt 1.4 and below does not support web workers in dev mode
|
||||||
|
$ npm run dev
|
||||||
|
|
||||||
|
# build for production and launch server
|
||||||
|
# in nuxt 1.4 and below you have to create a production build to use web workers
|
||||||
|
$ npm run build
|
||||||
|
$ npm start
|
||||||
|
|
||||||
|
# generate static project
|
||||||
|
$ npm run generate
|
||||||
|
```
|
||||||
|
|
||||||
|
For detailed explanation on how things work, checkout the [Nuxt.js docs](https://github.com/nuxt/nuxt.js).
|
8
examples/web-worker/assets/README.md
Normal file
8
examples/web-worker/assets/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# ASSETS
|
||||||
|
|
||||||
|
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
|
||||||
|
|
||||||
|
More information about the usage of this directory in the documentation:
|
||||||
|
https://nuxtjs.org/guide/assets#webpacked
|
||||||
|
|
||||||
|
**This directory is not required, you can delete it if you don't want to use it.**
|
17
examples/web-worker/assets/js/Example.worker.js
Normal file
17
examples/web-worker/assets/js/Example.worker.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// // block for `time` ms, then return the number of loops we could run in that time:
|
||||||
|
function expensive(time) {
|
||||||
|
let start = Date.now(),
|
||||||
|
count = 0
|
||||||
|
while (Date.now() - start < time) count++
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// Respond to message from parent thread
|
||||||
|
self.addEventListener('message', (event) => {
|
||||||
|
console.log('worker', event.data)
|
||||||
|
|
||||||
|
if (event.data.action === 'expensive' && event.data.time) {
|
||||||
|
// Post data to parent thread
|
||||||
|
self.postMessage(expensive(Number(event.data.time)))
|
||||||
|
}
|
||||||
|
})
|
79
examples/web-worker/components/AppLogo.vue
Normal file
79
examples/web-worker/components/AppLogo.vue
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<div class="VueToNuxtLogo">
|
||||||
|
<div class="Triangle Triangle--two"/>
|
||||||
|
<div class="Triangle Triangle--one"/>
|
||||||
|
<div class="Triangle Triangle--three"/>
|
||||||
|
<div class="Triangle Triangle--four"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.VueToNuxtLogo {
|
||||||
|
display: inline-block;
|
||||||
|
animation: turn 2s linear forwards 1s;
|
||||||
|
transform: rotateX(180deg);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 180px;
|
||||||
|
width: 245px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Triangle {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Triangle--one {
|
||||||
|
border-left: 105px solid transparent;
|
||||||
|
border-right: 105px solid transparent;
|
||||||
|
border-bottom: 180px solid #41B883;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Triangle--two {
|
||||||
|
top: 30px;
|
||||||
|
left: 35px;
|
||||||
|
animation: goright 0.5s linear forwards 3.5s;
|
||||||
|
border-left: 87.5px solid transparent;
|
||||||
|
border-right: 87.5px solid transparent;
|
||||||
|
border-bottom: 150px solid #3B8070;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Triangle--three {
|
||||||
|
top: 60px;
|
||||||
|
left: 35px;
|
||||||
|
animation: goright 0.5s linear forwards 3.5s;
|
||||||
|
border-left: 70px solid transparent;
|
||||||
|
border-right: 70px solid transparent;
|
||||||
|
border-bottom: 120px solid #35495E;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Triangle--four {
|
||||||
|
top: 120px;
|
||||||
|
left: 70px;
|
||||||
|
animation: godown 0.5s linear forwards 3s;
|
||||||
|
border-left: 35px solid transparent;
|
||||||
|
border-right: 35px solid transparent;
|
||||||
|
border-bottom: 60px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes turn {
|
||||||
|
100% {
|
||||||
|
transform: rotateX(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes godown {
|
||||||
|
100% {
|
||||||
|
top: 180px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes goright {
|
||||||
|
100% {
|
||||||
|
left: 70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
6
examples/web-worker/components/README.md
Normal file
6
examples/web-worker/components/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# COMPONENTS
|
||||||
|
|
||||||
|
The components directory contains your Vue.js Components.
|
||||||
|
Nuxt.js doesn't supercharge these components.
|
||||||
|
|
||||||
|
**This directory is not required, you can delete it if you don't want to use it.**
|
8
examples/web-worker/layouts/README.md
Normal file
8
examples/web-worker/layouts/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# LAYOUTS
|
||||||
|
|
||||||
|
This directory contains your Application Layouts.
|
||||||
|
|
||||||
|
More information about the usage of this directory in the documentation:
|
||||||
|
https://nuxtjs.org/guide/views#layouts
|
||||||
|
|
||||||
|
**This directory is not required, you can delete it if you don't want to use it.**
|
58
examples/web-worker/layouts/default.vue
Normal file
58
examples/web-worker/layouts/default.vue
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<nuxt/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
word-spacing: 1px;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
*, *:before, *:after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
margin-left: 15px;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button--green {
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #3b8070;
|
||||||
|
color: #3b8070;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 10px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button--green:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #3b8070;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button--grey {
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #35495e;
|
||||||
|
color: #35495e;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 10px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button--grey:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #35495e;
|
||||||
|
}
|
||||||
|
</style>
|
49
examples/web-worker/nuxt.config.js
Normal file
49
examples/web-worker/nuxt.config.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
module.exports = {
|
||||||
|
/*
|
||||||
|
** Headers of the page
|
||||||
|
*/
|
||||||
|
head: {
|
||||||
|
title: 'web-worker',
|
||||||
|
meta: [
|
||||||
|
{ charset: 'utf-8' },
|
||||||
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||||
|
{ hid: 'description', name: 'description', content: 'Nuxt.js project' }
|
||||||
|
],
|
||||||
|
link: [
|
||||||
|
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
** Customize the progress bar color
|
||||||
|
*/
|
||||||
|
loading: { color: '#3B8070' },
|
||||||
|
plugins: [
|
||||||
|
{ src: '~/plugins/inject-ww', ssr: false } // web workers are only available client-side, hence ssr: false
|
||||||
|
],
|
||||||
|
/*
|
||||||
|
** Build configuration
|
||||||
|
*/
|
||||||
|
build: {
|
||||||
|
/*
|
||||||
|
** Run ESLint on save
|
||||||
|
*/
|
||||||
|
extend (config, { isDev, isClient }) {
|
||||||
|
if (isDev && isClient) {
|
||||||
|
config.module.rules.push({
|
||||||
|
enforce: 'pre',
|
||||||
|
test: /\.(js|vue)$/,
|
||||||
|
loader: 'eslint-loader',
|
||||||
|
exclude: /(node_modules)/
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isClient) { // web workers are only available client-side
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /\.worker\.js$/, // this will pick up all .js files that ends with ".worker.js"
|
||||||
|
loader: 'worker-loader',
|
||||||
|
exclude: /(node_modules)/
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
examples/web-worker/package.json
Normal file
21
examples/web-worker/package.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "web-worker",
|
||||||
|
"description": "Demo web workers in nuxt.js",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nuxt",
|
||||||
|
"build": "nuxt build",
|
||||||
|
"start": "nuxt start",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
|
||||||
|
"precommit": "npm run lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"eslint": "^4.19.0",
|
||||||
|
"nuxt": "^1.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint-plugin-vue": "^4.3.0",
|
||||||
|
"worker-loader": "^1.1.1"
|
||||||
|
}
|
||||||
|
}
|
7
examples/web-worker/pages/README.md
Normal file
7
examples/web-worker/pages/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# PAGES
|
||||||
|
|
||||||
|
This directory contains your Application Views and Routes.
|
||||||
|
The framework reads all the .vue files inside this directory and creates the router of your application.
|
||||||
|
|
||||||
|
More information about the usage of this directory in the documentation:
|
||||||
|
https://nuxtjs.org/guide/routing
|
160
examples/web-worker/pages/index.vue
Normal file
160
examples/web-worker/pages/index.vue
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<template>
|
||||||
|
<section class="container">
|
||||||
|
<div>
|
||||||
|
<app-logo/>
|
||||||
|
<h1 class="title">
|
||||||
|
web-worker
|
||||||
|
</h1>
|
||||||
|
<h2 class="subtitle">
|
||||||
|
Nuxt.js project
|
||||||
|
</h2>
|
||||||
|
<p>{{ notification }}</p>
|
||||||
|
<ul class="list">
|
||||||
|
<li>Number of Web Workers: {{ workers.length }}</li>
|
||||||
|
<li>Number of long Running Workers: {{ longRunningWorkers.length }}</li>
|
||||||
|
<li>Number of unused Workers: {{ workers.filter(w => !w.inUse).length }}</li>
|
||||||
|
</ul>
|
||||||
|
<div class="links">
|
||||||
|
<a
|
||||||
|
:class="needWorkerSetup ? 'hidden' : 'visible'"
|
||||||
|
@click="test"
|
||||||
|
class="button button--green">Test Worker</a>
|
||||||
|
<a
|
||||||
|
:class="needWorkerSetup ? 'hidden' : 'visible'"
|
||||||
|
@click="long(4000)"
|
||||||
|
class="button button--green">Execute long running Worker</a>
|
||||||
|
<a
|
||||||
|
:class="needWorkerSetup || !longRunningWorkers.length ? 'hidden' : 'visible'"
|
||||||
|
@click="freeWorker"
|
||||||
|
class="button button--green">Free long running Worker</a>
|
||||||
|
<a
|
||||||
|
@click="removeWorker"
|
||||||
|
class="button button--grey">Remove Web Worker</a>
|
||||||
|
<a
|
||||||
|
@click="createWorkers"
|
||||||
|
class="button button--grey">Create more Workers</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AppLogo from '~/components/AppLogo.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
AppLogo
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
needWorkerSetup () {
|
||||||
|
return this.workers.length === 0 && this.longRunningWorkers.length === 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
notification: '',
|
||||||
|
workers: [],
|
||||||
|
workerIndex: 0,
|
||||||
|
longRunningWorkers: [],
|
||||||
|
longIndex: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
workers (workers) {
|
||||||
|
if (workers.length === 0) this.notification = 'Zero free Web Workers - click "Create more Workers"'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
test () {
|
||||||
|
const worker = this.workers[this.workerIndex++ % this.workers.length]
|
||||||
|
|
||||||
|
if (worker) worker.postMessage({ hello: 'world' })
|
||||||
|
else this.notification = 'No more test workers available'
|
||||||
|
},
|
||||||
|
long (miliseconds) {
|
||||||
|
let worker = this.workers.shift()
|
||||||
|
|
||||||
|
if (worker) {
|
||||||
|
worker.onmessage = (event) => {
|
||||||
|
console.log(`expensive made ${event.data} loops`)
|
||||||
|
}
|
||||||
|
this.longRunningWorkers.push(worker)
|
||||||
|
} else {
|
||||||
|
worker = this.longRunningWorkers[ this.longIndex++ % this.longRunningWorkers.length]
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.postMessage({ action: 'expensive', time: miliseconds })
|
||||||
|
},
|
||||||
|
freeWorker () {
|
||||||
|
const worker = this.longRunningWorkers.pop()
|
||||||
|
worker.onmessage = null
|
||||||
|
this.workers.push(worker)
|
||||||
|
this.notification = 'Worker freed'
|
||||||
|
},
|
||||||
|
removeWorker () {
|
||||||
|
const worker = this.workers.pop() || this.longRunningWorkers.pop()
|
||||||
|
|
||||||
|
if (!worker) return
|
||||||
|
|
||||||
|
if (this.longRunningWorkers.indexOf(worker) > -1) this.longRunningWorkers.splice(this.longRunningWorkers.indexOf(worker), 1)
|
||||||
|
|
||||||
|
worker.onmessage = null
|
||||||
|
worker.terminate()
|
||||||
|
},
|
||||||
|
createWorkers () {
|
||||||
|
if (process.browser) {
|
||||||
|
for(let i = 0, len = navigator.hardwareConcurrency || 1; i < len; i++) {
|
||||||
|
this.workers.push(this.$worker.createWorker())
|
||||||
|
}
|
||||||
|
|
||||||
|
this.notification = 'Go nuts!'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visible {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; /* 1 */
|
||||||
|
display: block;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 100px;
|
||||||
|
color: #35495e;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 42px;
|
||||||
|
color: #526488;
|
||||||
|
word-spacing: 5px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.links {
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
text-align: left;
|
||||||
|
color: #526488;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
</style>
|
8
examples/web-worker/plugins/README.md
Normal file
8
examples/web-worker/plugins/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# PLUGINS
|
||||||
|
|
||||||
|
This directory contains your Javascript plugins that you want to run before instantiating the root vue.js application.
|
||||||
|
|
||||||
|
More information about the usage of this directory in the documentation:
|
||||||
|
https://nuxtjs.org/guide/plugins
|
||||||
|
|
||||||
|
**This directory is not required, you can delete it if you don't want to use it.**
|
9
examples/web-worker/plugins/inject-ww.js
Normal file
9
examples/web-worker/plugins/inject-ww.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import ExampleWorker from '~/assets/js/Example.worker.js' // worker files has to end in ".worker.js" - see nuxt.config.js
|
||||||
|
|
||||||
|
export default (context, inject) => {
|
||||||
|
inject('worker', {
|
||||||
|
createWorker () {
|
||||||
|
return new ExampleWorker()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
11
examples/web-worker/static/README.md
Normal file
11
examples/web-worker/static/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# STATIC
|
||||||
|
|
||||||
|
This directory contains your static files.
|
||||||
|
Each file inside this directory is mapped to /.
|
||||||
|
|
||||||
|
Example: /static/robots.txt is mapped as /robots.txt.
|
||||||
|
|
||||||
|
More information about the usage of this directory in the documentation:
|
||||||
|
https://nuxtjs.org/guide/assets#static
|
||||||
|
|
||||||
|
**This directory is not required, you can delete it if you don't want to use it.**
|
BIN
examples/web-worker/static/favicon.ico
Normal file
BIN
examples/web-worker/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Loading…
Reference in New Issue
Block a user