2017-10-15 86 views
4

我想用bookmarklet-loader和style-loader和css-loader创建小书签。但是我无法将css导入到我的小书签中。使用webpack,bookmarklet-loader,style和css-loader创建小书签

这是我

webpack.config.js:

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 /书签工具/ 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); 

只需添加小书签t o空白页面上的链接,所以我可以将链接添加到我的浏览器。

但运行webpack产生这个错误:

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

我尝试添加以下到我的webpack.config.js:

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

现在这编译罚款,但书签代码包含需要语句,所以当我尝试并在浏览器中运行时,我得到一个

Uncaught ReferenceError: require is not defined

我发现了thisthis,但一直无法使其工作。

编辑: 简单地解释问题和解决方案。我正在尝试构建一个小书签,但是我正在使用的小书签加载器用于将小书签导入其他代码段。而且,这个书签小工具加载程序并未设置为处理小书签所需的CSS和模板。我已经切换到使用一个简单的webpack配置,产生一个编译的JavaScript文件,然后this工具将其转换为书签。

这是我的情况下,如果的package.json帮助其人:

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

现在npm run build构建书签,并将其复制到我的剪贴板所以我可以更新浏览器的书签。

+0

请问为什么不直接发布自己的解决方案作为答案? – ghybs

回答

3

我猜的WebPack书签装载机不需要创建书签本身,GitHub的回购建议 “书签装载机是的WebPack装载机,将任何JavaScript文件转换为书签,可以用来作为整个模块你的应用程序。“ 不清楚,如果这是你的用例。

看插件代码,

'use strict'; 

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

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

我怀疑问题可能是因为这里唯一使用的包装是Uglifyjs只编译JavaScript和代码中没有CSS装载机。 这个插件希望你的代码是纯JS,而不是任何CSS和HTML。

从你的代码我看到你已经配置webpack已经建立的CSS和JS,并且所有这些代码提供给您的是JavaScript URI模式包装在一个URI编码的函数中。在webpack构建输出之后, 应该非常简单。 希望有所帮助!

+0

我想要一个包含CSS和HTML的书签。我该怎么做呢?我试着在我的问题中提到的加载器中添加'style-loader','css-loader'。但是这些介绍需要在浏览器上失败的js代码中声明。我怎样才能做到这一点 - 一个CSS和HTML书签? – arunkumar

+0

我看到类似的讨论,'var script = document.createElement(“script”); script.setAttribute(“type”,“text/javascript”); script.setAttribute(“src”,“http://www.example.com/file.js”); document.getElementsByTagName(“head”)[0] .appendChild(script);'https://stackoverflow.com/questions/22336786/overlay-one-iframe-on-top-of-another-scroll-them-together/22337897#22337897 –

+0

上述代码在[本站点](https://mrcoles.com/bookmarklet/)上转换为小书签后,您可以在书签位置字段中添加以下代码并进行测试。 '的javascript:(函数()%7Bvar%20script%20%3D%20document.createElement(%22script%22)%3Bscript。的setAttribute(%22type%22%2C%20%22text%2Fjavascript%22)%3Bscript.setAttribute(%22src%22%2C%20%22http%3A%2F%2Fwww.example.com%2Ffile.js%22)% 3Bdocument.getElementsByTagName(%22head%22)%5B0%5D.appendChild(script)%7D)()'https://stackoverflow.com/questions/22336786/overlay-one-iframe-on-top-of-another-滚动它们在一起/ 22337897#22337897' –

5

我也发现这个问题很有意思,所以这里的答案仍然会让你使用webpack捆绑你的书签代码。

的想法是使用一个<script>标签并通过的WebPack服务内容作为块:

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

随着一些aditional的 '魔力',您index.js变为:

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"; 

这是上述函数的简化版本,它引用了您的'bookmarklet.bundle.js'块。 (这样,你并不真正需要的书签装载机更多)

bookmarklet.js源(只是一个示例):

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); 

其中someOtherSource.js可能是简单如:

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

最后,您webpack.config.js变为:

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" ], 
     }) 
    ] 
}; 

再次,利用我在这里看到的是,你用你的WebPack捆绑,CSS构建您的书签/更少或任何其他装载机。作为参考也参见firstsecond

2

您在编辑中详细描述的解决方案确实是实现您的目标的完美方法。

您想保留bookmarklet,这取决于注射样式。

虽然您可以轻松地将带有书签的标签(例如<link><script>)插入到当前页面中,但它似乎不符合您的需求,因为您不需要在服务器上提供代码,并试图链接文件系统上的本地资源可能不太可靠。

因此,您需要将整个代码和样式包含在小书签代码中。您可以在2个步骤进行:

  1. 捆绑与内联CSS注入+ CSS
  2. 编码代码的JS代码,敷包,这样它的内容可以作为一个书签。

1。捆绑JS代码为内联CSS注入

这听起来像是一个完美的webpack工作!事实上,它的目的是捆绑你的代码,并将你的样式嵌入到代码中,像style-loader一样。

您甚至可以通过确保CSS中可能引用的任何其他资源(图片,Web字体等)也使用和limit: 0来始终内联这些资源来进一步推动它。

但是,正如你所想的那样,你不应该使用中间的人为因素(例如bookmarklet-loader的输出),因为他们可能会遗漏一些功能(导入风格,require)。

您正在寻找webpack输出包:a standalone将内联样式注入当前页面并执行代码的JavaScript代码。

2编码和包装的书签

将代码转换为书签,你必须为URI兼容的内容进行编码,并添加一个额外的“javascript:”前缀。

这是您使用bookmarklet包的步骤。但是,在你的情况,因为你已经是要“硬编码”到书签的JavaScript文件,包装是死的简单:

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

您可以继续使用bookmarklet包或使其成为一个非常简单的节点脚本(但您应该在上一步中移动缩小步骤,通常在webpack配置中)。

其实,这是很容易做出的WebPack插件这个“bookmarkletify”的步骤:

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(); 
    }); 
}; 

有了这些额外的步骤(资源内联,CSS和JS缩小,bookmarkletify资产),您的WebPack配置将be:

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() 
    ] 
}; 

dist/index.js文件的内容现在已准备好被复制为书签。