2017-10-15 2 views
4

Ich versuche ein Bookmarklet mit bookmarklet-loader und dem Style-Loader und css-loader zu erstellen. Aber ich habe Probleme beim Importieren von CSS in mein Bookmarklet.Erstellen eines Bookmarklet mit webpack, bookmarklet-loader, style und css-loader

Dies ist, was ich

webpack.config.js haben:

const path = require('path'); 
const HtmlWebpackPlugin = require('html-webpack-plugin'); 
const CleanWebpackPlugin = require('clean-webpack-plugin'); 

module.exports = { 
entry: { 
    index: './src/index.js', 
    bookmarklet: './src/bookmarklets/bookmarklet.js' 
}, 
output: { 
    filename: '[name].bundle.js', 
    path: path.resolve(__dirname, 'dist') 
}, 
target: 'web', 
module: { 
    rules: [ 
    { 
     test: /\.css$/, 
     use: [ 
      'style-loader', 
      'css-loader' 
     ] 
    }, 
    { 
     test: /\.js$/, 
     use: [ 
      'bookmarklet-loader' 
     ], 
     include: path.join(__dirname, './src/bookmarklets') 
    } 
    ] 
}, 
plugins: [ 
    new CleanWebpackPlugin(['dist']), 
    new HtmlWebpackPlugin({ 
     title: 'Development' 
    }) 
] 

src/Bookmarklets/bookmarklet.js:

import './css/style.css'; 

/* the rest of my bookmarklet code */ 

src/index.js:

import bookmarklet from './bookmarklets/bookmarklet'; 

var add = document.createElement("a"); 
add.href = "javascript:" + bookmarklet; 
add.innerHTML = "Click me"; 

document.body.appendChild(add); 

Fügt einfach das Bookmarklet t hinzu o ein Link auf einer leeren Seite, damit ich den Link zu meinem Browser hinzufügen kann.

Aber webpack läuft erzeugt diesen Fehler:

SyntaxError: Unexpected token: string (./css/style.css) at [snipped] node_modules/uglify-js/tools/node.js

Ich habe versucht, die folgenden meiner webpack.config.js fügte hinzu:

{ 
    test: /\.js$/, 
    use: [ 
     'bookmarklet-loader', 
     'style-loader', 
     'css-loader' 
    ], 
    include: path.join(__dirname, './src/bookmarklets') 
} 

Das jetzt kompiliert gut, aber der Bookmarklet-Code enthält require statements, also wenn ich es im Browser starte und erhalte ich eine

Uncaught ReferenceError: require is not defined

Ich habe this und this gefunden, aber es konnte nicht funktionieren.

Bearbeiten: Um einfach die Frage und Lösung zu erklären. Ich versuche, ein Bookmarklet zu erstellen, aber der Bookmarklet-Loader, den ich verwende, wird zum Importieren von Bookmarklets in andere Codeabschnitte verwendet. Und dieser Bookmarklet-Loader ist insbesondere nicht eingerichtet, CSS und Templates zu verarbeiten, die für das Bookmarklet benötigt werden. Ich habe zu einer einfachen Webpack-Konfiguration gewechselt, die eine kompilierte Javascript-Datei erstellt und dann this Werkzeug, um das zu einem Bookmarklet zu konvertieren.

Das ist mein package.json im Falle, wenn seine Hilfe an jedermann:

<snip> 
"scripts": { 
     "build": "webpack && bookmarklet dist/index.js dist/bookmarklet.js && cat dist/bookmarklet.js | xclip -selection clipboard", 
} 

Jetzt npm run build baut das Bookmarklet und kopiert ihn in meine Zwischenablage, so kann ich das Bookmarklet im Browser aktualisieren.

+0

Bitte, warum postest du deine eigene Lösung nicht direkt als Antwort? – ghybs

Antwort

3

Ich denke, webpack Bookmarklet Lader ist nicht erforderlich, ein Bookmarklet selbst zu schaffen, wie die GitHub Repo schlägt „Bookmarklet-loader ein webpack Loader ist, die jede JavaScript-Datei in ein Bookmarklet konvertieren , die als Modul verwendet werden kann überall Ihre Anwendung " Nicht klar, ob das Ihr Anwendungsfall ist.

im Plugin-Code suchen,

'use strict'; 

var uglify = require('uglify-js'); 

module.exports = function(source) { 
    return 'module.exports = "javascript:' + encodeURIComponent(
    '(function(){'+ uglify.minify(source, { fromString: true }).code +'})();' 
) + '"'; 
}; 

Ich vermute, das Problem sein könnte, weil das einzige Paket hier verwendet Uglifyjs ist das nur Javascript erstellt, und es werden keine CSS-Lader im Code. Dieses Plugin erwartet, dass Ihr Code reines JS und kein CSS und HTML ist.

Aus Ihrem Code sehe ich, dass Sie Webpack bereits konfiguriert haben, um CSS und JS zu bauen, und all dieser Code bietet Ihnen Javascript uri Muster in eine Funktion eingewickelt, die URI codiert ist. sollte nach dem Webpack-Build-Output ziemlich einfach zu DIY sein. hoffe das hilft!

+0

Ich möchte ein Bookmarklet, das CSS und HTML enthält. Wie kann ich das tun? Ich habe versucht, den Loadern 'style-loader', 'css-loader' hinzuzufügen, wie in meiner Frage erwähnt. Aber diese eingeführt erfordern Anweisungen im js-Code, die im Browser fehlschlagen. Wie kann ich das erreichen - ein Bookmarklet mit CSS und HTML? – arunkumar

+0

Ich sehe eine ähnliche Diskussion, 'var script = document.createElement (" script "); script.setAttribute ("type", "text/javascript"); script.setAttribute ("src", "http://www.example.com/file.js"); document.getElementsByTagName ("Kopf") [0] .appendChild (Skript); 'https://Stackoverflow.com/questions/22336786/overlay-one-iframe-on-top-of-another-scroll-them-together/22337897 # 22337897 –

+0

Der obige Code nach dem Konvertieren in Bookmarklet auf [dieser Site] (https://mrcoles.com/bookmarklet/), können Sie unten Code in Ihrem Lesezeichen Standort Feld hinzufügen und testen. 'javascript: (function()% 7Bvar% 20% script% 20% 3D% 20document.createElement (% 22script% 22)% 3Bscript.setAttribute (% 22Typ% 22% 2C% 20% 22Text% 2Fjavascript% 22)% 3Bscript.setAttribute (% 22src% 22% 2C% 20% 22http% 3A% 2F% 2Fwww.beispiel.com% 2Ffile.js% 22)% 3Bdocument.getElementsByTagName (% 22head% 22)% 5B0% 5D.appendChild (Skript)% 7D)() 'https://stackoverflow.com/questions/22336786/overlay-one-iframe-on-top-of-another- scroll-them-together/22337897 # 22337897' –

5

Ich habe auch diese Frage interessant gefunden, also hier ist eine Antwort, die Sie noch Webpack für die Bündelung Ihres Bookmarklet-Codes verwenden würde.

Die Idee ist es, einen <script> Tag zu verwenden und den Inhalt als ein Stück durch webpack dienen:

function addScript(codeURL) { 
    const scriptElement = document.createElement('script'); 
    scriptElement.setAttribute('src', codeURL); 
    scriptElement.setAttribute('crossorigin', "anonymous"); 
    document.body.appendChild(scriptElement); 
} 

Mit etwas aditional 'Magie', Ihre index.js werden:

const add = document.createElement("a"); 
add.href = "javascript:(function(){s=document.createElement('script');s.type='text/javascript';s.src='bookmarklet.bundle.js';document.body.appendChild(s);})()"; 
add.innerHTML = "Click me"; 

die ist die Uglified-Version der obigen Funktion, die auf Ihre 'bookmarklet.bundle.js' Chunk verweist. (Auf diese Weise brauchen Sie nicht wirklich die Bookmarklet-loader mehr)

Die bookmarklet.js Quelle (nur ein Beispiel):

import './css/style.css'; 

let elements = require('./someOtherSource'); 

let list = document.createElement('ul'); 
for (let i = 0; i < elements.length; ++i) { 
    let item = document.createElement('li'); 
    item.appendChild(document.createTextNode(elements[i])); 
    list.appendChild(item); 
} 
document.body.appendChild(list); 

wo someOtherSource.js könnte so einfach sein wie:

module.exports = [ 'a', 'b', 'c']; 

und schließlich Ihre webpack.config.js wird:

const path = require('path'); 
const HtmlWebpackPlugin = require('html-webpack-plugin'); 
const CleanWebpackPlugin = require('clean-webpack-plugin'); 

module.exports = { 
    entry: { 
     index: path.resolve(__dirname, 'src/index.js'), 
     bookmarklet: path.resolve(__dirname, 'src/bookmarklets/bookmarklet.js'), 
    }, 
    output: { 
     filename: '[name].bundle.js', 
     path: path.resolve(__dirname, 'dist') 
    }, 
    target: 'web', 
    module: { 
     rules: [ 
      { 
       test: /\.css$/, 
       use: [ 
        'style-loader', 
        'css-loader', 
       ] 
      }, 
      { 
       test: /\.js$/, 
       use: [ 
        'babel-loader', 
       ], 
       exclude: /node_modules/, 
      } 
     ] 
    }, 
    plugins: [ 
     new CleanWebpackPlugin(['dist']), 
     new HtmlWebpackPlugin({ 
      title: 'Bookmarklet', 
      chunks: [ "index" ], 
     }) 
    ] 
}; 

Auch hier ist der Vorteil, den ich hier sehe, ist, dass Sie Ihre webpack Bündelung verwenden bekommen, CSS/weniger oder was auch immer andere Lader für Ihren Bookmarklet zu bauen. Siehe auch first und second.

2

Die Lösung, die Sie in Ihrer Bearbeitung detailliert beschreiben, ist in der Tat eine vollkommen gültige Methode, um Ihr Ziel zu erreichen.

Sie möchten eine bookmarklet pflegen, die von den Einspritzungsstilen abhängt.

Während Sie einfach Tags (wie <link> und <script>) mit einem Bookmarklet injizieren können, um externe Ressourcen in die aktuelle Seite zu laden, scheint es nicht Ihren Anforderungen zu entsprechen, da Sie Ihren Code nicht auf einem Server verfügbar machen müssen. und versuchen, lokale Ressourcen in Ihrem Dateisystem zu verknüpfen, ist möglicherweise nicht sehr zuverlässig.

Daher möchten Sie die vollständigen Code und Stile in den Bookmarklet-Code enthalten sein. Sie können in zwei Schritten vorgehen:

  1. Bundle Ihre JS-Code mit dem Code für die Inline-CSS-Injektion + CSS
  2. Encode und wickeln das Bündel, so dass dessen Inhalt als Lesezeichen verwendet werden können.

1.Bundle JS mit Code für Inline-CSS-Injektion

Das klingt nach einem perfekten Job für Webpack! In der Tat ist es beabsichtigt, Ihren Code zu bündeln und Ihre Stile innerhalb des Codes mit style-loader wie Sie auch inline.

Sie es sogar, indem sichergestellt anderer Vermögenswert (Bild, Web-Schriftart, etc.), die möglicherweise Bezug genommen wird in Ihrem CSS auch, url-loader mit einem limit: 0 mit etwas weiter drücken könnten, ist inlined immer diese Ressourcen inline.

Aber wie Sie herausgefunden, sollten Sie nicht die Zwischen Artefakte verwenden (wie zum Beispiel die Ausgabe von bookmarklet-loader), da sie wahrscheinlich einige Funktionen vermissen (Import Stil, require).

Das Webpack-Ausgabepaket ist genau das, wonach Sie suchen: ein standalone JavaScript-Code, der Inline-Stile in die aktuelle Seite einfügt und Ihren Code ausführt.

2. Encode und wickeln für Lesezeichen

Um den Code in ein Bookmarklet zu konvertieren, müssen Sie den Inhalt für die URI-Kompatibilität codieren, und fügen Sie ein extra "javascript:" erfolgen.

Dies ist der Schritt, in dem Sie das Paket bookmarklet verwendet haben. Aber in Ihrem Fall, da alles, was Sie haben, ist ein einzelne JavaScript-Datei, die Sie „hard-Code“ in das Bookmarklet wollen, die Hülle ist tot einfach:

'javascript:' + encodeURIComponent('(function(){' + code + '})()') 

Sie können weiterhin mit bookmarklet Paket oder mache es zu einem sehr einfachen Node-Skript (aber du solltest den Minifikationsschritt in einem vorherigen Schritt verschieben, normalerweise in der Webpack-Konfiguration).

Eigentlich ist es ganz einfach, ein webpack Plugin für diesen "bookmarkletify" Schritt zu machen:

function AssetToBookmarkletPlugin() {} 

AssetToBookmarkletPlugin.prototype.apply = function (compiler) { 
    compiler.plugin('emit', function (compilation, callback) { 
    var asset; 

    // Rework each asset. 
    for (var assetName in compilation.assets) { 
     asset = compilation.assets[assetName]; 
     compilation.assets[assetName] = { 
     source: function() { 
      // Encode and wrap the original source to make it bookmark-ready. 
      return 'javascript:' + encodeURIComponent('(function(){' + asset.source() + '})()'); 
     }, 
     size: asset.size 
     } 
    } 

    callback(); 
    }); 
}; 

Mit diesen zusätzlichen Schritten (Ressourcen-Inlining, CSS und JS minification, bookmarkletify Vermögenswerte), Ihre webpack Konfiguration würde sein:

const webpack = require('webpack'); 
const path = require('path'); 

module.exports = { 
    entry: { 
    index: './src/index.js' 
    }, 
    output: { 
    filename: '[name].js', 
    path: path.resolve(__dirname, 'dist') 
    }, 
    target: 'web', 
    module: { 
    rules: [{ 
     test: /\.(png|jpg|gif)$/, 
     use: [{ 
     loader: 'url-loader', 
     options: {limit: 0} // 0 = always inline resource 
     }] 
    }, { 
     test: /\.css$/, 
     use: ['style-loader', { 
     loader: 'css-loader', 
     options: {minimize: true} // Minify CSS as well 
     }] 
    }] 
    }, 
    plugins: [ 
    new webpack.optimize.UglifyJsPlugin(), 
    new AssetToBookmarkletPlugin() 
    ] 
}; 

der Inhalt dist/index.js Datei als Lesezeichen kopiert werden jetzt fertig ist.

Verwandte Themen